istereo

diff libs/libpng/pngrtran.c @ 26:862a3329a8f0

wohooo, added a shitload of code from zlib/libpng/libjpeg. When the good lord was raining shared libraries the iphone held a fucking umbrella...
author John Tsiombikas <nuclear@mutantstargoat.com>
date Thu, 08 Sep 2011 06:28:38 +0300
parents
children
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/libs/libpng/pngrtran.c	Thu Sep 08 06:28:38 2011 +0300
     1.3 @@ -0,0 +1,4296 @@
     1.4 +
     1.5 +/* pngrtran.c - transforms the data in a row for PNG readers
     1.6 + *
     1.7 + * Last changed in libpng 1.2.30 [August 15, 2008]
     1.8 + * For conditions of distribution and use, see copyright notice in png.h
     1.9 + * Copyright (c) 1998-2008 Glenn Randers-Pehrson
    1.10 + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
    1.11 + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
    1.12 + *
    1.13 + * This file contains functions optionally called by an application
    1.14 + * in order to tell libpng how to handle data when reading a PNG.
    1.15 + * Transformations that are used in both reading and writing are
    1.16 + * in pngtrans.c.
    1.17 + */
    1.18 +
    1.19 +#define PNG_INTERNAL
    1.20 +#include "png.h"
    1.21 +#if defined(PNG_READ_SUPPORTED)
    1.22 +
    1.23 +/* Set the action on getting a CRC error for an ancillary or critical chunk. */
    1.24 +void PNGAPI
    1.25 +png_set_crc_action(png_structp png_ptr, int crit_action, int ancil_action)
    1.26 +{
    1.27 +   png_debug(1, "in png_set_crc_action\n");
    1.28 +   /* Tell libpng how we react to CRC errors in critical chunks */
    1.29 +   if (png_ptr == NULL) return;
    1.30 +   switch (crit_action)
    1.31 +   {
    1.32 +      case PNG_CRC_NO_CHANGE:                        /* leave setting as is */
    1.33 +         break;
    1.34 +      case PNG_CRC_WARN_USE:                               /* warn/use data */
    1.35 +         png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
    1.36 +         png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE;
    1.37 +         break;
    1.38 +      case PNG_CRC_QUIET_USE:                             /* quiet/use data */
    1.39 +         png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
    1.40 +         png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE |
    1.41 +                           PNG_FLAG_CRC_CRITICAL_IGNORE;
    1.42 +         break;
    1.43 +      case PNG_CRC_WARN_DISCARD:    /* not a valid action for critical data */
    1.44 +         png_warning(png_ptr,
    1.45 +            "Can't discard critical data on CRC error.");
    1.46 +      case PNG_CRC_ERROR_QUIT:                                /* error/quit */
    1.47 +      case PNG_CRC_DEFAULT:
    1.48 +      default:
    1.49 +         png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
    1.50 +         break;
    1.51 +   }
    1.52 +
    1.53 +   switch (ancil_action)
    1.54 +   {
    1.55 +      case PNG_CRC_NO_CHANGE:                       /* leave setting as is */
    1.56 +         break;
    1.57 +      case PNG_CRC_WARN_USE:                              /* warn/use data */
    1.58 +         png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
    1.59 +         png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE;
    1.60 +         break;
    1.61 +      case PNG_CRC_QUIET_USE:                            /* quiet/use data */
    1.62 +         png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
    1.63 +         png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE |
    1.64 +                           PNG_FLAG_CRC_ANCILLARY_NOWARN;
    1.65 +         break;
    1.66 +      case PNG_CRC_ERROR_QUIT:                               /* error/quit */
    1.67 +         png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
    1.68 +         png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN;
    1.69 +         break;
    1.70 +      case PNG_CRC_WARN_DISCARD:                      /* warn/discard data */
    1.71 +      case PNG_CRC_DEFAULT:
    1.72 +      default:
    1.73 +         png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
    1.74 +         break;
    1.75 +   }
    1.76 +}
    1.77 +
    1.78 +#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
    1.79 +    defined(PNG_FLOATING_POINT_SUPPORTED)
    1.80 +/* handle alpha and tRNS via a background color */
    1.81 +void PNGAPI
    1.82 +png_set_background(png_structp png_ptr,
    1.83 +   png_color_16p background_color, int background_gamma_code,
    1.84 +   int need_expand, double background_gamma)
    1.85 +{
    1.86 +   png_debug(1, "in png_set_background\n");
    1.87 +   if (png_ptr == NULL) return;
    1.88 +   if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN)
    1.89 +   {
    1.90 +      png_warning(png_ptr, "Application must supply a known background gamma");
    1.91 +      return;
    1.92 +   }
    1.93 +
    1.94 +   png_ptr->transformations |= PNG_BACKGROUND;
    1.95 +   png_memcpy(&(png_ptr->background), background_color,
    1.96 +      png_sizeof(png_color_16));
    1.97 +   png_ptr->background_gamma = (float)background_gamma;
    1.98 +   png_ptr->background_gamma_type = (png_byte)(background_gamma_code);
    1.99 +   png_ptr->transformations |= (need_expand ? PNG_BACKGROUND_EXPAND : 0);
   1.100 +}
   1.101 +#endif
   1.102 +
   1.103 +#if defined(PNG_READ_16_TO_8_SUPPORTED)
   1.104 +/* strip 16 bit depth files to 8 bit depth */
   1.105 +void PNGAPI
   1.106 +png_set_strip_16(png_structp png_ptr)
   1.107 +{
   1.108 +   png_debug(1, "in png_set_strip_16\n");
   1.109 +   if (png_ptr == NULL) return;
   1.110 +   png_ptr->transformations |= PNG_16_TO_8;
   1.111 +}
   1.112 +#endif
   1.113 +
   1.114 +#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
   1.115 +void PNGAPI
   1.116 +png_set_strip_alpha(png_structp png_ptr)
   1.117 +{
   1.118 +   png_debug(1, "in png_set_strip_alpha\n");
   1.119 +   if (png_ptr == NULL) return;
   1.120 +   png_ptr->flags |= PNG_FLAG_STRIP_ALPHA;
   1.121 +}
   1.122 +#endif
   1.123 +
   1.124 +#if defined(PNG_READ_DITHER_SUPPORTED)
   1.125 +/* Dither file to 8 bit.  Supply a palette, the current number
   1.126 + * of elements in the palette, the maximum number of elements
   1.127 + * allowed, and a histogram if possible.  If the current number
   1.128 + * of colors is greater then the maximum number, the palette will be
   1.129 + * modified to fit in the maximum number.  "full_dither" indicates
   1.130 + * whether we need a dithering cube set up for RGB images, or if we
   1.131 + * simply are reducing the number of colors in a paletted image.
   1.132 + */
   1.133 +
   1.134 +typedef struct png_dsort_struct
   1.135 +{
   1.136 +   struct png_dsort_struct FAR * next;
   1.137 +   png_byte left;
   1.138 +   png_byte right;
   1.139 +} png_dsort;
   1.140 +typedef png_dsort FAR *       png_dsortp;
   1.141 +typedef png_dsort FAR * FAR * png_dsortpp;
   1.142 +
   1.143 +void PNGAPI
   1.144 +png_set_dither(png_structp png_ptr, png_colorp palette,
   1.145 +   int num_palette, int maximum_colors, png_uint_16p histogram,
   1.146 +   int full_dither)
   1.147 +{
   1.148 +   png_debug(1, "in png_set_dither\n");
   1.149 +   if (png_ptr == NULL) return;
   1.150 +   png_ptr->transformations |= PNG_DITHER;
   1.151 +
   1.152 +   if (!full_dither)
   1.153 +   {
   1.154 +      int i;
   1.155 +
   1.156 +      png_ptr->dither_index = (png_bytep)png_malloc(png_ptr,
   1.157 +         (png_uint_32)(num_palette * png_sizeof(png_byte)));
   1.158 +      for (i = 0; i < num_palette; i++)
   1.159 +         png_ptr->dither_index[i] = (png_byte)i;
   1.160 +   }
   1.161 +
   1.162 +   if (num_palette > maximum_colors)
   1.163 +   {
   1.164 +      if (histogram != NULL)
   1.165 +      {
   1.166 +         /* This is easy enough, just throw out the least used colors.
   1.167 +            Perhaps not the best solution, but good enough. */
   1.168 +
   1.169 +         int i;
   1.170 +
   1.171 +         /* initialize an array to sort colors */
   1.172 +         png_ptr->dither_sort = (png_bytep)png_malloc(png_ptr,
   1.173 +            (png_uint_32)(num_palette * png_sizeof(png_byte)));
   1.174 +
   1.175 +         /* initialize the dither_sort array */
   1.176 +         for (i = 0; i < num_palette; i++)
   1.177 +            png_ptr->dither_sort[i] = (png_byte)i;
   1.178 +
   1.179 +         /* Find the least used palette entries by starting a
   1.180 +            bubble sort, and running it until we have sorted
   1.181 +            out enough colors.  Note that we don't care about
   1.182 +            sorting all the colors, just finding which are
   1.183 +            least used. */
   1.184 +
   1.185 +         for (i = num_palette - 1; i >= maximum_colors; i--)
   1.186 +         {
   1.187 +            int done; /* to stop early if the list is pre-sorted */
   1.188 +            int j;
   1.189 +
   1.190 +            done = 1;
   1.191 +            for (j = 0; j < i; j++)
   1.192 +            {
   1.193 +               if (histogram[png_ptr->dither_sort[j]]
   1.194 +                   < histogram[png_ptr->dither_sort[j + 1]])
   1.195 +               {
   1.196 +                  png_byte t;
   1.197 +
   1.198 +                  t = png_ptr->dither_sort[j];
   1.199 +                  png_ptr->dither_sort[j] = png_ptr->dither_sort[j + 1];
   1.200 +                  png_ptr->dither_sort[j + 1] = t;
   1.201 +                  done = 0;
   1.202 +               }
   1.203 +            }
   1.204 +            if (done)
   1.205 +               break;
   1.206 +         }
   1.207 +
   1.208 +         /* swap the palette around, and set up a table, if necessary */
   1.209 +         if (full_dither)
   1.210 +         {
   1.211 +            int j = num_palette;
   1.212 +
   1.213 +            /* put all the useful colors within the max, but don't
   1.214 +               move the others */
   1.215 +            for (i = 0; i < maximum_colors; i++)
   1.216 +            {
   1.217 +               if ((int)png_ptr->dither_sort[i] >= maximum_colors)
   1.218 +               {
   1.219 +                  do
   1.220 +                     j--;
   1.221 +                  while ((int)png_ptr->dither_sort[j] >= maximum_colors);
   1.222 +                  palette[i] = palette[j];
   1.223 +               }
   1.224 +            }
   1.225 +         }
   1.226 +         else
   1.227 +         {
   1.228 +            int j = num_palette;
   1.229 +
   1.230 +            /* move all the used colors inside the max limit, and
   1.231 +               develop a translation table */
   1.232 +            for (i = 0; i < maximum_colors; i++)
   1.233 +            {
   1.234 +               /* only move the colors we need to */
   1.235 +               if ((int)png_ptr->dither_sort[i] >= maximum_colors)
   1.236 +               {
   1.237 +                  png_color tmp_color;
   1.238 +
   1.239 +                  do
   1.240 +                     j--;
   1.241 +                  while ((int)png_ptr->dither_sort[j] >= maximum_colors);
   1.242 +
   1.243 +                  tmp_color = palette[j];
   1.244 +                  palette[j] = palette[i];
   1.245 +                  palette[i] = tmp_color;
   1.246 +                  /* indicate where the color went */
   1.247 +                  png_ptr->dither_index[j] = (png_byte)i;
   1.248 +                  png_ptr->dither_index[i] = (png_byte)j;
   1.249 +               }
   1.250 +            }
   1.251 +
   1.252 +            /* find closest color for those colors we are not using */
   1.253 +            for (i = 0; i < num_palette; i++)
   1.254 +            {
   1.255 +               if ((int)png_ptr->dither_index[i] >= maximum_colors)
   1.256 +               {
   1.257 +                  int min_d, k, min_k, d_index;
   1.258 +
   1.259 +                  /* find the closest color to one we threw out */
   1.260 +                  d_index = png_ptr->dither_index[i];
   1.261 +                  min_d = PNG_COLOR_DIST(palette[d_index], palette[0]);
   1.262 +                  for (k = 1, min_k = 0; k < maximum_colors; k++)
   1.263 +                  {
   1.264 +                     int d;
   1.265 +
   1.266 +                     d = PNG_COLOR_DIST(palette[d_index], palette[k]);
   1.267 +
   1.268 +                     if (d < min_d)
   1.269 +                     {
   1.270 +                        min_d = d;
   1.271 +                        min_k = k;
   1.272 +                     }
   1.273 +                  }
   1.274 +                  /* point to closest color */
   1.275 +                  png_ptr->dither_index[i] = (png_byte)min_k;
   1.276 +               }
   1.277 +            }
   1.278 +         }
   1.279 +         png_free(png_ptr, png_ptr->dither_sort);
   1.280 +         png_ptr->dither_sort = NULL;
   1.281 +      }
   1.282 +      else
   1.283 +      {
   1.284 +         /* This is much harder to do simply (and quickly).  Perhaps
   1.285 +            we need to go through a median cut routine, but those
   1.286 +            don't always behave themselves with only a few colors
   1.287 +            as input.  So we will just find the closest two colors,
   1.288 +            and throw out one of them (chosen somewhat randomly).
   1.289 +            [We don't understand this at all, so if someone wants to
   1.290 +             work on improving it, be our guest - AED, GRP]
   1.291 +            */
   1.292 +         int i;
   1.293 +         int max_d;
   1.294 +         int num_new_palette;
   1.295 +         png_dsortp t;
   1.296 +         png_dsortpp hash;
   1.297 +
   1.298 +         t = NULL;
   1.299 +
   1.300 +         /* initialize palette index arrays */
   1.301 +         png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr,
   1.302 +            (png_uint_32)(num_palette * png_sizeof(png_byte)));
   1.303 +         png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr,
   1.304 +            (png_uint_32)(num_palette * png_sizeof(png_byte)));
   1.305 +
   1.306 +         /* initialize the sort array */
   1.307 +         for (i = 0; i < num_palette; i++)
   1.308 +         {
   1.309 +            png_ptr->index_to_palette[i] = (png_byte)i;
   1.310 +            png_ptr->palette_to_index[i] = (png_byte)i;
   1.311 +         }
   1.312 +
   1.313 +         hash = (png_dsortpp)png_malloc(png_ptr, (png_uint_32)(769 *
   1.314 +            png_sizeof(png_dsortp)));
   1.315 +         for (i = 0; i < 769; i++)
   1.316 +            hash[i] = NULL;
   1.317 +/*         png_memset(hash, 0, 769 * png_sizeof(png_dsortp)); */
   1.318 +
   1.319 +         num_new_palette = num_palette;
   1.320 +
   1.321 +         /* initial wild guess at how far apart the farthest pixel
   1.322 +            pair we will be eliminating will be.  Larger
   1.323 +            numbers mean more areas will be allocated, Smaller
   1.324 +            numbers run the risk of not saving enough data, and
   1.325 +            having to do this all over again.
   1.326 +
   1.327 +            I have not done extensive checking on this number.
   1.328 +            */
   1.329 +         max_d = 96;
   1.330 +
   1.331 +         while (num_new_palette > maximum_colors)
   1.332 +         {
   1.333 +            for (i = 0; i < num_new_palette - 1; i++)
   1.334 +            {
   1.335 +               int j;
   1.336 +
   1.337 +               for (j = i + 1; j < num_new_palette; j++)
   1.338 +               {
   1.339 +                  int d;
   1.340 +
   1.341 +                  d = PNG_COLOR_DIST(palette[i], palette[j]);
   1.342 +
   1.343 +                  if (d <= max_d)
   1.344 +                  {
   1.345 +
   1.346 +                     t = (png_dsortp)png_malloc_warn(png_ptr,
   1.347 +                         (png_uint_32)(png_sizeof(png_dsort)));
   1.348 +                     if (t == NULL)
   1.349 +                         break;
   1.350 +                     t->next = hash[d];
   1.351 +                     t->left = (png_byte)i;
   1.352 +                     t->right = (png_byte)j;
   1.353 +                     hash[d] = t;
   1.354 +                  }
   1.355 +               }
   1.356 +               if (t == NULL)
   1.357 +                  break;
   1.358 +            }
   1.359 +
   1.360 +            if (t != NULL)
   1.361 +            for (i = 0; i <= max_d; i++)
   1.362 +            {
   1.363 +               if (hash[i] != NULL)
   1.364 +               {
   1.365 +                  png_dsortp p;
   1.366 +
   1.367 +                  for (p = hash[i]; p; p = p->next)
   1.368 +                  {
   1.369 +                     if ((int)png_ptr->index_to_palette[p->left]
   1.370 +                        < num_new_palette &&
   1.371 +                        (int)png_ptr->index_to_palette[p->right]
   1.372 +                        < num_new_palette)
   1.373 +                     {
   1.374 +                        int j, next_j;
   1.375 +
   1.376 +                        if (num_new_palette & 0x01)
   1.377 +                        {
   1.378 +                           j = p->left;
   1.379 +                           next_j = p->right;
   1.380 +                        }
   1.381 +                        else
   1.382 +                        {
   1.383 +                           j = p->right;
   1.384 +                           next_j = p->left;
   1.385 +                        }
   1.386 +
   1.387 +                        num_new_palette--;
   1.388 +                        palette[png_ptr->index_to_palette[j]]
   1.389 +                          = palette[num_new_palette];
   1.390 +                        if (!full_dither)
   1.391 +                        {
   1.392 +                           int k;
   1.393 +
   1.394 +                           for (k = 0; k < num_palette; k++)
   1.395 +                           {
   1.396 +                              if (png_ptr->dither_index[k] ==
   1.397 +                                 png_ptr->index_to_palette[j])
   1.398 +                                 png_ptr->dither_index[k] =
   1.399 +                                    png_ptr->index_to_palette[next_j];
   1.400 +                              if ((int)png_ptr->dither_index[k] ==
   1.401 +                                 num_new_palette)
   1.402 +                                 png_ptr->dither_index[k] =
   1.403 +                                    png_ptr->index_to_palette[j];
   1.404 +                           }
   1.405 +                        }
   1.406 +
   1.407 +                        png_ptr->index_to_palette[png_ptr->palette_to_index
   1.408 +                           [num_new_palette]] = png_ptr->index_to_palette[j];
   1.409 +                        png_ptr->palette_to_index[png_ptr->index_to_palette[j]]
   1.410 +                           = png_ptr->palette_to_index[num_new_palette];
   1.411 +
   1.412 +                        png_ptr->index_to_palette[j] = (png_byte)num_new_palette;
   1.413 +                        png_ptr->palette_to_index[num_new_palette] = (png_byte)j;
   1.414 +                     }
   1.415 +                     if (num_new_palette <= maximum_colors)
   1.416 +                        break;
   1.417 +                  }
   1.418 +                  if (num_new_palette <= maximum_colors)
   1.419 +                     break;
   1.420 +               }
   1.421 +            }
   1.422 +
   1.423 +            for (i = 0; i < 769; i++)
   1.424 +            {
   1.425 +               if (hash[i] != NULL)
   1.426 +               {
   1.427 +                  png_dsortp p = hash[i];
   1.428 +                  while (p)
   1.429 +                  {
   1.430 +                     t = p->next;
   1.431 +                     png_free(png_ptr, p);
   1.432 +                     p = t;
   1.433 +                  }
   1.434 +               }
   1.435 +               hash[i] = 0;
   1.436 +            }
   1.437 +            max_d += 96;
   1.438 +         }
   1.439 +         png_free(png_ptr, hash);
   1.440 +         png_free(png_ptr, png_ptr->palette_to_index);
   1.441 +         png_free(png_ptr, png_ptr->index_to_palette);
   1.442 +         png_ptr->palette_to_index = NULL;
   1.443 +         png_ptr->index_to_palette = NULL;
   1.444 +      }
   1.445 +      num_palette = maximum_colors;
   1.446 +   }
   1.447 +   if (png_ptr->palette == NULL)
   1.448 +   {
   1.449 +      png_ptr->palette = palette;
   1.450 +   }
   1.451 +   png_ptr->num_palette = (png_uint_16)num_palette;
   1.452 +
   1.453 +   if (full_dither)
   1.454 +   {
   1.455 +      int i;
   1.456 +      png_bytep distance;
   1.457 +      int total_bits = PNG_DITHER_RED_BITS + PNG_DITHER_GREEN_BITS +
   1.458 +         PNG_DITHER_BLUE_BITS;
   1.459 +      int num_red = (1 << PNG_DITHER_RED_BITS);
   1.460 +      int num_green = (1 << PNG_DITHER_GREEN_BITS);
   1.461 +      int num_blue = (1 << PNG_DITHER_BLUE_BITS);
   1.462 +      png_size_t num_entries = ((png_size_t)1 << total_bits);
   1.463 +
   1.464 +      png_ptr->palette_lookup = (png_bytep )png_malloc(png_ptr,
   1.465 +         (png_uint_32)(num_entries * png_sizeof(png_byte)));
   1.466 +
   1.467 +      png_memset(png_ptr->palette_lookup, 0, num_entries *
   1.468 +         png_sizeof(png_byte));
   1.469 +
   1.470 +      distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries *
   1.471 +         png_sizeof(png_byte)));
   1.472 +
   1.473 +      png_memset(distance, 0xff, num_entries * png_sizeof(png_byte));
   1.474 +
   1.475 +      for (i = 0; i < num_palette; i++)
   1.476 +      {
   1.477 +         int ir, ig, ib;
   1.478 +         int r = (palette[i].red >> (8 - PNG_DITHER_RED_BITS));
   1.479 +         int g = (palette[i].green >> (8 - PNG_DITHER_GREEN_BITS));
   1.480 +         int b = (palette[i].blue >> (8 - PNG_DITHER_BLUE_BITS));
   1.481 +
   1.482 +         for (ir = 0; ir < num_red; ir++)
   1.483 +         {
   1.484 +            /* int dr = abs(ir - r); */
   1.485 +            int dr = ((ir > r) ? ir - r : r - ir);
   1.486 +            int index_r = (ir << (PNG_DITHER_BLUE_BITS + PNG_DITHER_GREEN_BITS));
   1.487 +
   1.488 +            for (ig = 0; ig < num_green; ig++)
   1.489 +            {
   1.490 +               /* int dg = abs(ig - g); */
   1.491 +               int dg = ((ig > g) ? ig - g : g - ig);
   1.492 +               int dt = dr + dg;
   1.493 +               int dm = ((dr > dg) ? dr : dg);
   1.494 +               int index_g = index_r | (ig << PNG_DITHER_BLUE_BITS);
   1.495 +
   1.496 +               for (ib = 0; ib < num_blue; ib++)
   1.497 +               {
   1.498 +                  int d_index = index_g | ib;
   1.499 +                  /* int db = abs(ib - b); */
   1.500 +                  int db = ((ib > b) ? ib - b : b - ib);
   1.501 +                  int dmax = ((dm > db) ? dm : db);
   1.502 +                  int d = dmax + dt + db;
   1.503 +
   1.504 +                  if (d < (int)distance[d_index])
   1.505 +                  {
   1.506 +                     distance[d_index] = (png_byte)d;
   1.507 +                     png_ptr->palette_lookup[d_index] = (png_byte)i;
   1.508 +                  }
   1.509 +               }
   1.510 +            }
   1.511 +         }
   1.512 +      }
   1.513 +
   1.514 +      png_free(png_ptr, distance);
   1.515 +   }
   1.516 +}
   1.517 +#endif
   1.518 +
   1.519 +#if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
   1.520 +/* Transform the image from the file_gamma to the screen_gamma.  We
   1.521 + * only do transformations on images where the file_gamma and screen_gamma
   1.522 + * are not close reciprocals, otherwise it slows things down slightly, and
   1.523 + * also needlessly introduces small errors.
   1.524 + *
   1.525 + * We will turn off gamma transformation later if no semitransparent entries
   1.526 + * are present in the tRNS array for palette images.  We can't do it here
   1.527 + * because we don't necessarily have the tRNS chunk yet.
   1.528 + */
   1.529 +void PNGAPI
   1.530 +png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma)
   1.531 +{
   1.532 +   png_debug(1, "in png_set_gamma\n");
   1.533 +   if (png_ptr == NULL) return;
   1.534 +   if ((fabs(scrn_gamma * file_gamma - 1.0) > PNG_GAMMA_THRESHOLD) ||
   1.535 +       (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) ||
   1.536 +       (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))
   1.537 +     png_ptr->transformations |= PNG_GAMMA;
   1.538 +   png_ptr->gamma = (float)file_gamma;
   1.539 +   png_ptr->screen_gamma = (float)scrn_gamma;
   1.540 +}
   1.541 +#endif
   1.542 +
   1.543 +#if defined(PNG_READ_EXPAND_SUPPORTED)
   1.544 +/* Expand paletted images to RGB, expand grayscale images of
   1.545 + * less than 8-bit depth to 8-bit depth, and expand tRNS chunks
   1.546 + * to alpha channels.
   1.547 + */
   1.548 +void PNGAPI
   1.549 +png_set_expand(png_structp png_ptr)
   1.550 +{
   1.551 +   png_debug(1, "in png_set_expand\n");
   1.552 +   if (png_ptr == NULL) return;
   1.553 +   png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
   1.554 +   png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
   1.555 +}
   1.556 +
   1.557 +/* GRR 19990627:  the following three functions currently are identical
   1.558 + *  to png_set_expand().  However, it is entirely reasonable that someone
   1.559 + *  might wish to expand an indexed image to RGB but *not* expand a single,
   1.560 + *  fully transparent palette entry to a full alpha channel--perhaps instead
   1.561 + *  convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace
   1.562 + *  the transparent color with a particular RGB value, or drop tRNS entirely.
   1.563 + *  IOW, a future version of the library may make the transformations flag
   1.564 + *  a bit more fine-grained, with separate bits for each of these three
   1.565 + *  functions.
   1.566 + *
   1.567 + *  More to the point, these functions make it obvious what libpng will be
   1.568 + *  doing, whereas "expand" can (and does) mean any number of things.
   1.569 + *
   1.570 + *  GRP 20060307: In libpng-1.4.0, png_set_gray_1_2_4_to_8() was modified
   1.571 + *  to expand only the sample depth but not to expand the tRNS to alpha.
   1.572 + */
   1.573 +
   1.574 +/* Expand paletted images to RGB. */
   1.575 +void PNGAPI
   1.576 +png_set_palette_to_rgb(png_structp png_ptr)
   1.577 +{
   1.578 +   png_debug(1, "in png_set_palette_to_rgb\n");
   1.579 +   if (png_ptr == NULL) return;
   1.580 +   png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
   1.581 +   png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
   1.582 +}
   1.583 +
   1.584 +#if !defined(PNG_1_0_X)
   1.585 +/* Expand grayscale images of less than 8-bit depth to 8 bits. */
   1.586 +void PNGAPI
   1.587 +png_set_expand_gray_1_2_4_to_8(png_structp png_ptr)
   1.588 +{
   1.589 +   png_debug(1, "in png_set_expand_gray_1_2_4_to_8\n");
   1.590 +   if (png_ptr == NULL) return;
   1.591 +   png_ptr->transformations |= PNG_EXPAND;
   1.592 +   png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
   1.593 +}
   1.594 +#endif
   1.595 +
   1.596 +#if defined(PNG_1_0_X) || defined(PNG_1_2_X)
   1.597 +/* Expand grayscale images of less than 8-bit depth to 8 bits. */
   1.598 +/* Deprecated as of libpng-1.2.9 */
   1.599 +void PNGAPI
   1.600 +png_set_gray_1_2_4_to_8(png_structp png_ptr)
   1.601 +{
   1.602 +   png_debug(1, "in png_set_gray_1_2_4_to_8\n");
   1.603 +   if (png_ptr == NULL) return;
   1.604 +   png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
   1.605 +}
   1.606 +#endif
   1.607 +
   1.608 +
   1.609 +/* Expand tRNS chunks to alpha channels. */
   1.610 +void PNGAPI
   1.611 +png_set_tRNS_to_alpha(png_structp png_ptr)
   1.612 +{
   1.613 +   png_debug(1, "in png_set_tRNS_to_alpha\n");
   1.614 +   png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
   1.615 +   png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
   1.616 +}
   1.617 +#endif /* defined(PNG_READ_EXPAND_SUPPORTED) */
   1.618 +
   1.619 +#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
   1.620 +void PNGAPI
   1.621 +png_set_gray_to_rgb(png_structp png_ptr)
   1.622 +{
   1.623 +   png_debug(1, "in png_set_gray_to_rgb\n");
   1.624 +   png_ptr->transformations |= PNG_GRAY_TO_RGB;
   1.625 +   png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
   1.626 +}
   1.627 +#endif
   1.628 +
   1.629 +#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
   1.630 +#if defined(PNG_FLOATING_POINT_SUPPORTED)
   1.631 +/* Convert a RGB image to a grayscale of the same width.  This allows us,
   1.632 + * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image.
   1.633 + */
   1.634 +
   1.635 +void PNGAPI
   1.636 +png_set_rgb_to_gray(png_structp png_ptr, int error_action, double red,
   1.637 +   double green)
   1.638 +{
   1.639 +      int red_fixed = (int)((float)red*100000.0 + 0.5);
   1.640 +      int green_fixed = (int)((float)green*100000.0 + 0.5);
   1.641 +      if (png_ptr == NULL) return;
   1.642 +      png_set_rgb_to_gray_fixed(png_ptr, error_action, red_fixed, green_fixed);
   1.643 +}
   1.644 +#endif
   1.645 +
   1.646 +void PNGAPI
   1.647 +png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action,
   1.648 +   png_fixed_point red, png_fixed_point green)
   1.649 +{
   1.650 +   png_debug(1, "in png_set_rgb_to_gray\n");
   1.651 +   if (png_ptr == NULL) return;
   1.652 +   switch(error_action)
   1.653 +   {
   1.654 +      case 1: png_ptr->transformations |= PNG_RGB_TO_GRAY;
   1.655 +              break;
   1.656 +      case 2: png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN;
   1.657 +              break;
   1.658 +      case 3: png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR;
   1.659 +   }
   1.660 +   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
   1.661 +#if defined(PNG_READ_EXPAND_SUPPORTED)
   1.662 +      png_ptr->transformations |= PNG_EXPAND;
   1.663 +#else
   1.664 +   {
   1.665 +      png_warning(png_ptr,
   1.666 +        "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED.");
   1.667 +      png_ptr->transformations &= ~PNG_RGB_TO_GRAY;
   1.668 +   }
   1.669 +#endif
   1.670 +   {
   1.671 +      png_uint_16 red_int, green_int;
   1.672 +      if (red < 0 || green < 0)
   1.673 +      {
   1.674 +         red_int   =  6968; /* .212671 * 32768 + .5 */
   1.675 +         green_int = 23434; /* .715160 * 32768 + .5 */
   1.676 +      }
   1.677 +      else if (red + green < 100000L)
   1.678 +      {
   1.679 +        red_int = (png_uint_16)(((png_uint_32)red*32768L)/100000L);
   1.680 +        green_int = (png_uint_16)(((png_uint_32)green*32768L)/100000L);
   1.681 +      }
   1.682 +      else
   1.683 +      {
   1.684 +         png_warning(png_ptr, "ignoring out of range rgb_to_gray coefficients");
   1.685 +         red_int   =  6968;
   1.686 +         green_int = 23434;
   1.687 +      }
   1.688 +      png_ptr->rgb_to_gray_red_coeff   = red_int;
   1.689 +      png_ptr->rgb_to_gray_green_coeff = green_int;
   1.690 +      png_ptr->rgb_to_gray_blue_coeff  = 
   1.691 +         (png_uint_16)(32768 - red_int - green_int);
   1.692 +   }
   1.693 +}
   1.694 +#endif
   1.695 +
   1.696 +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
   1.697 +    defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \
   1.698 +    defined(PNG_LEGACY_SUPPORTED)
   1.699 +void PNGAPI
   1.700 +png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr
   1.701 +   read_user_transform_fn)
   1.702 +{
   1.703 +   png_debug(1, "in png_set_read_user_transform_fn\n");
   1.704 +   if (png_ptr == NULL) return;
   1.705 +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
   1.706 +   png_ptr->transformations |= PNG_USER_TRANSFORM;
   1.707 +   png_ptr->read_user_transform_fn = read_user_transform_fn;
   1.708 +#endif
   1.709 +#ifdef PNG_LEGACY_SUPPORTED
   1.710 +   if (read_user_transform_fn)
   1.711 +      png_warning(png_ptr,
   1.712 +        "This version of libpng does not support user transforms");
   1.713 +#endif
   1.714 +}
   1.715 +#endif
   1.716 +
   1.717 +/* Initialize everything needed for the read.  This includes modifying
   1.718 + * the palette.
   1.719 + */
   1.720 +void /* PRIVATE */
   1.721 +png_init_read_transformations(png_structp png_ptr)
   1.722 +{
   1.723 +   png_debug(1, "in png_init_read_transformations\n");
   1.724 +#if defined(PNG_USELESS_TESTS_SUPPORTED)
   1.725 +   if (png_ptr != NULL)
   1.726 +#endif
   1.727 +  {
   1.728 +#if defined(PNG_READ_BACKGROUND_SUPPORTED) || defined(PNG_READ_SHIFT_SUPPORTED) \
   1.729 + || defined(PNG_READ_GAMMA_SUPPORTED)
   1.730 +   int color_type = png_ptr->color_type;
   1.731 +#endif
   1.732 +
   1.733 +#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
   1.734 +
   1.735 +#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
   1.736 +   /* Detect gray background and attempt to enable optimization
   1.737 +    * for gray --> RGB case */
   1.738 +   /* Note:  if PNG_BACKGROUND_EXPAND is set and color_type is either RGB or
   1.739 +    * RGB_ALPHA (in which case need_expand is superfluous anyway), the
   1.740 +    * background color might actually be gray yet not be flagged as such.
   1.741 +    * This is not a problem for the current code, which uses
   1.742 +    * PNG_BACKGROUND_IS_GRAY only to decide when to do the
   1.743 +    * png_do_gray_to_rgb() transformation.
   1.744 +    */
   1.745 +   if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
   1.746 +       !(color_type & PNG_COLOR_MASK_COLOR))
   1.747 +   {
   1.748 +          png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
   1.749 +   } else if ((png_ptr->transformations & PNG_BACKGROUND) &&
   1.750 +              !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
   1.751 +              (png_ptr->transformations & PNG_GRAY_TO_RGB) &&
   1.752 +              png_ptr->background.red == png_ptr->background.green &&
   1.753 +              png_ptr->background.red == png_ptr->background.blue)
   1.754 +   {
   1.755 +          png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
   1.756 +          png_ptr->background.gray = png_ptr->background.red;
   1.757 +   }
   1.758 +#endif
   1.759 +
   1.760 +   if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
   1.761 +       (png_ptr->transformations & PNG_EXPAND))
   1.762 +   {
   1.763 +      if (!(color_type & PNG_COLOR_MASK_COLOR))  /* i.e., GRAY or GRAY_ALPHA */
   1.764 +      {
   1.765 +         /* expand background and tRNS chunks */
   1.766 +         switch (png_ptr->bit_depth)
   1.767 +         {
   1.768 +            case 1:
   1.769 +               png_ptr->background.gray *= (png_uint_16)0xff;
   1.770 +               png_ptr->background.red = png_ptr->background.green
   1.771 +                 =  png_ptr->background.blue = png_ptr->background.gray;
   1.772 +               if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
   1.773 +               {
   1.774 +                 png_ptr->trans_values.gray *= (png_uint_16)0xff;
   1.775 +                 png_ptr->trans_values.red = png_ptr->trans_values.green
   1.776 +                   = png_ptr->trans_values.blue = png_ptr->trans_values.gray;
   1.777 +               }
   1.778 +               break;
   1.779 +            case 2:
   1.780 +               png_ptr->background.gray *= (png_uint_16)0x55;
   1.781 +               png_ptr->background.red = png_ptr->background.green
   1.782 +                 = png_ptr->background.blue = png_ptr->background.gray;
   1.783 +               if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
   1.784 +               {
   1.785 +                 png_ptr->trans_values.gray *= (png_uint_16)0x55;
   1.786 +                 png_ptr->trans_values.red = png_ptr->trans_values.green
   1.787 +                   = png_ptr->trans_values.blue = png_ptr->trans_values.gray;
   1.788 +               }
   1.789 +               break;
   1.790 +            case 4:
   1.791 +               png_ptr->background.gray *= (png_uint_16)0x11;
   1.792 +               png_ptr->background.red = png_ptr->background.green
   1.793 +                 = png_ptr->background.blue = png_ptr->background.gray;
   1.794 +               if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
   1.795 +               {
   1.796 +                 png_ptr->trans_values.gray *= (png_uint_16)0x11;
   1.797 +                 png_ptr->trans_values.red = png_ptr->trans_values.green
   1.798 +                   = png_ptr->trans_values.blue = png_ptr->trans_values.gray;
   1.799 +               }
   1.800 +               break;
   1.801 +            case 8:
   1.802 +            case 16:
   1.803 +               png_ptr->background.red = png_ptr->background.green
   1.804 +                 = png_ptr->background.blue = png_ptr->background.gray;
   1.805 +               break;
   1.806 +         }
   1.807 +      }
   1.808 +      else if (color_type == PNG_COLOR_TYPE_PALETTE)
   1.809 +      {
   1.810 +         png_ptr->background.red   =
   1.811 +            png_ptr->palette[png_ptr->background.index].red;
   1.812 +         png_ptr->background.green =
   1.813 +            png_ptr->palette[png_ptr->background.index].green;
   1.814 +         png_ptr->background.blue  =
   1.815 +            png_ptr->palette[png_ptr->background.index].blue;
   1.816 +
   1.817 +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
   1.818 +        if (png_ptr->transformations & PNG_INVERT_ALPHA)
   1.819 +        {
   1.820 +#if defined(PNG_READ_EXPAND_SUPPORTED)
   1.821 +           if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
   1.822 +#endif
   1.823 +           {
   1.824 +           /* invert the alpha channel (in tRNS) unless the pixels are
   1.825 +              going to be expanded, in which case leave it for later */
   1.826 +              int i, istop;
   1.827 +              istop=(int)png_ptr->num_trans;
   1.828 +              for (i=0; i<istop; i++)
   1.829 +                 png_ptr->trans[i] = (png_byte)(255 - png_ptr->trans[i]);
   1.830 +           }
   1.831 +        }
   1.832 +#endif
   1.833 +
   1.834 +      }
   1.835 +   }
   1.836 +#endif
   1.837 +
   1.838 +#if defined(PNG_READ_BACKGROUND_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
   1.839 +   png_ptr->background_1 = png_ptr->background;
   1.840 +#endif
   1.841 +#if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
   1.842 +
   1.843 +   if ((color_type == PNG_COLOR_TYPE_PALETTE && png_ptr->num_trans != 0)
   1.844 +       && (fabs(png_ptr->screen_gamma * png_ptr->gamma - 1.0)
   1.845 +         < PNG_GAMMA_THRESHOLD))
   1.846 +   {
   1.847 +    int i, k;
   1.848 +    k=0;
   1.849 +    for (i=0; i<png_ptr->num_trans; i++)
   1.850 +    {
   1.851 +      if (png_ptr->trans[i] != 0 && png_ptr->trans[i] != 0xff)
   1.852 +        k=1; /* partial transparency is present */
   1.853 +    }
   1.854 +    if (k == 0)
   1.855 +      png_ptr->transformations &= ~PNG_GAMMA;
   1.856 +   }
   1.857 +
   1.858 +   if ((png_ptr->transformations & (PNG_GAMMA | PNG_RGB_TO_GRAY)) &&
   1.859 +        png_ptr->gamma != 0.0)
   1.860 +   {
   1.861 +      png_build_gamma_table(png_ptr);
   1.862 +#if defined(PNG_READ_BACKGROUND_SUPPORTED)
   1.863 +      if (png_ptr->transformations & PNG_BACKGROUND)
   1.864 +      {
   1.865 +         if (color_type == PNG_COLOR_TYPE_PALETTE)
   1.866 +         {
   1.867 +           /* could skip if no transparency and
   1.868 +           */
   1.869 +            png_color back, back_1;
   1.870 +            png_colorp palette = png_ptr->palette;
   1.871 +            int num_palette = png_ptr->num_palette;
   1.872 +            int i;
   1.873 +            if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
   1.874 +            {
   1.875 +               back.red = png_ptr->gamma_table[png_ptr->background.red];
   1.876 +               back.green = png_ptr->gamma_table[png_ptr->background.green];
   1.877 +               back.blue = png_ptr->gamma_table[png_ptr->background.blue];
   1.878 +
   1.879 +               back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
   1.880 +               back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
   1.881 +               back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
   1.882 +            }
   1.883 +            else
   1.884 +            {
   1.885 +               double g, gs;
   1.886 +
   1.887 +               switch (png_ptr->background_gamma_type)
   1.888 +               {
   1.889 +                  case PNG_BACKGROUND_GAMMA_SCREEN:
   1.890 +                     g = (png_ptr->screen_gamma);
   1.891 +                     gs = 1.0;
   1.892 +                     break;
   1.893 +                  case PNG_BACKGROUND_GAMMA_FILE:
   1.894 +                     g = 1.0 / (png_ptr->gamma);
   1.895 +                     gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
   1.896 +                     break;
   1.897 +                  case PNG_BACKGROUND_GAMMA_UNIQUE:
   1.898 +                     g = 1.0 / (png_ptr->background_gamma);
   1.899 +                     gs = 1.0 / (png_ptr->background_gamma *
   1.900 +                                 png_ptr->screen_gamma);
   1.901 +                     break;
   1.902 +                  default:
   1.903 +                     g = 1.0;    /* back_1 */
   1.904 +                     gs = 1.0;   /* back */
   1.905 +               }
   1.906 +
   1.907 +               if ( fabs(gs - 1.0) < PNG_GAMMA_THRESHOLD)
   1.908 +               {
   1.909 +                  back.red   = (png_byte)png_ptr->background.red;
   1.910 +                  back.green = (png_byte)png_ptr->background.green;
   1.911 +                  back.blue  = (png_byte)png_ptr->background.blue;
   1.912 +               }
   1.913 +               else
   1.914 +               {
   1.915 +                  back.red = (png_byte)(pow(
   1.916 +                     (double)png_ptr->background.red/255, gs) * 255.0 + .5);
   1.917 +                  back.green = (png_byte)(pow(
   1.918 +                     (double)png_ptr->background.green/255, gs) * 255.0 + .5);
   1.919 +                  back.blue = (png_byte)(pow(
   1.920 +                     (double)png_ptr->background.blue/255, gs) * 255.0 + .5);
   1.921 +               }
   1.922 +
   1.923 +               back_1.red = (png_byte)(pow(
   1.924 +                  (double)png_ptr->background.red/255, g) * 255.0 + .5);
   1.925 +               back_1.green = (png_byte)(pow(
   1.926 +                  (double)png_ptr->background.green/255, g) * 255.0 + .5);
   1.927 +               back_1.blue = (png_byte)(pow(
   1.928 +                  (double)png_ptr->background.blue/255, g) * 255.0 + .5);
   1.929 +            }
   1.930 +            for (i = 0; i < num_palette; i++)
   1.931 +            {
   1.932 +               if (i < (int)png_ptr->num_trans && png_ptr->trans[i] != 0xff)
   1.933 +               {
   1.934 +                  if (png_ptr->trans[i] == 0)
   1.935 +                  {
   1.936 +                     palette[i] = back;
   1.937 +                  }
   1.938 +                  else /* if (png_ptr->trans[i] != 0xff) */
   1.939 +                  {
   1.940 +                     png_byte v, w;
   1.941 +
   1.942 +                     v = png_ptr->gamma_to_1[palette[i].red];
   1.943 +                     png_composite(w, v, png_ptr->trans[i], back_1.red);
   1.944 +                     palette[i].red = png_ptr->gamma_from_1[w];
   1.945 +
   1.946 +                     v = png_ptr->gamma_to_1[palette[i].green];
   1.947 +                     png_composite(w, v, png_ptr->trans[i], back_1.green);
   1.948 +                     palette[i].green = png_ptr->gamma_from_1[w];
   1.949 +
   1.950 +                     v = png_ptr->gamma_to_1[palette[i].blue];
   1.951 +                     png_composite(w, v, png_ptr->trans[i], back_1.blue);
   1.952 +                     palette[i].blue = png_ptr->gamma_from_1[w];
   1.953 +                  }
   1.954 +               }
   1.955 +               else
   1.956 +               {
   1.957 +                  palette[i].red = png_ptr->gamma_table[palette[i].red];
   1.958 +                  palette[i].green = png_ptr->gamma_table[palette[i].green];
   1.959 +                  palette[i].blue = png_ptr->gamma_table[palette[i].blue];
   1.960 +               }
   1.961 +            }
   1.962 +	    /* Prevent the transformations being done again, and make sure
   1.963 +	     * that the now spurious alpha channel is stripped - the code
   1.964 +	     * has just reduced background composition and gamma correction
   1.965 +	     * to a simple alpha channel strip.
   1.966 +	     */
   1.967 +	    png_ptr->transformations &= ~PNG_BACKGROUND;
   1.968 +	    png_ptr->transformations &= ~PNG_GAMMA;
   1.969 +	    png_ptr->transformations |= PNG_STRIP_ALPHA;
   1.970 +         }
   1.971 +         /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */
   1.972 +         else
   1.973 +         /* color_type != PNG_COLOR_TYPE_PALETTE */
   1.974 +         {
   1.975 +            double m = (double)(((png_uint_32)1 << png_ptr->bit_depth) - 1);
   1.976 +            double g = 1.0;
   1.977 +            double gs = 1.0;
   1.978 +
   1.979 +            switch (png_ptr->background_gamma_type)
   1.980 +            {
   1.981 +               case PNG_BACKGROUND_GAMMA_SCREEN:
   1.982 +                  g = (png_ptr->screen_gamma);
   1.983 +                  gs = 1.0;
   1.984 +                  break;
   1.985 +               case PNG_BACKGROUND_GAMMA_FILE:
   1.986 +                  g = 1.0 / (png_ptr->gamma);
   1.987 +                  gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
   1.988 +                  break;
   1.989 +               case PNG_BACKGROUND_GAMMA_UNIQUE:
   1.990 +                  g = 1.0 / (png_ptr->background_gamma);
   1.991 +                  gs = 1.0 / (png_ptr->background_gamma *
   1.992 +                     png_ptr->screen_gamma);
   1.993 +                  break;
   1.994 +            }
   1.995 +
   1.996 +            png_ptr->background_1.gray = (png_uint_16)(pow(
   1.997 +               (double)png_ptr->background.gray / m, g) * m + .5);
   1.998 +            png_ptr->background.gray = (png_uint_16)(pow(
   1.999 +               (double)png_ptr->background.gray / m, gs) * m + .5);
  1.1000 +
  1.1001 +            if ((png_ptr->background.red != png_ptr->background.green) ||
  1.1002 +                (png_ptr->background.red != png_ptr->background.blue) ||
  1.1003 +                (png_ptr->background.red != png_ptr->background.gray))
  1.1004 +            {
  1.1005 +               /* RGB or RGBA with color background */
  1.1006 +               png_ptr->background_1.red = (png_uint_16)(pow(
  1.1007 +                  (double)png_ptr->background.red / m, g) * m + .5);
  1.1008 +               png_ptr->background_1.green = (png_uint_16)(pow(
  1.1009 +                  (double)png_ptr->background.green / m, g) * m + .5);
  1.1010 +               png_ptr->background_1.blue = (png_uint_16)(pow(
  1.1011 +                  (double)png_ptr->background.blue / m, g) * m + .5);
  1.1012 +               png_ptr->background.red = (png_uint_16)(pow(
  1.1013 +                  (double)png_ptr->background.red / m, gs) * m + .5);
  1.1014 +               png_ptr->background.green = (png_uint_16)(pow(
  1.1015 +                  (double)png_ptr->background.green / m, gs) * m + .5);
  1.1016 +               png_ptr->background.blue = (png_uint_16)(pow(
  1.1017 +                  (double)png_ptr->background.blue / m, gs) * m + .5);
  1.1018 +            }
  1.1019 +            else
  1.1020 +            {
  1.1021 +               /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */
  1.1022 +               png_ptr->background_1.red = png_ptr->background_1.green
  1.1023 +                 = png_ptr->background_1.blue = png_ptr->background_1.gray;
  1.1024 +               png_ptr->background.red = png_ptr->background.green
  1.1025 +                 = png_ptr->background.blue = png_ptr->background.gray;
  1.1026 +            }
  1.1027 +         }
  1.1028 +      }
  1.1029 +      else
  1.1030 +      /* transformation does not include PNG_BACKGROUND */
  1.1031 +#endif /* PNG_READ_BACKGROUND_SUPPORTED */
  1.1032 +      if (color_type == PNG_COLOR_TYPE_PALETTE)
  1.1033 +      {
  1.1034 +         png_colorp palette = png_ptr->palette;
  1.1035 +         int num_palette = png_ptr->num_palette;
  1.1036 +         int i;
  1.1037 +
  1.1038 +         for (i = 0; i < num_palette; i++)
  1.1039 +         {
  1.1040 +            palette[i].red = png_ptr->gamma_table[palette[i].red];
  1.1041 +            palette[i].green = png_ptr->gamma_table[palette[i].green];
  1.1042 +            palette[i].blue = png_ptr->gamma_table[palette[i].blue];
  1.1043 +         }
  1.1044 +
  1.1045 +	 /* Done the gamma correction. */
  1.1046 +	 png_ptr->transformations &= ~PNG_GAMMA;
  1.1047 +      }
  1.1048 +   }
  1.1049 +#if defined(PNG_READ_BACKGROUND_SUPPORTED)
  1.1050 +   else
  1.1051 +#endif
  1.1052 +#endif /* PNG_READ_GAMMA_SUPPORTED && PNG_FLOATING_POINT_SUPPORTED */
  1.1053 +#if defined(PNG_READ_BACKGROUND_SUPPORTED)
  1.1054 +   /* No GAMMA transformation */
  1.1055 +   if ((png_ptr->transformations & PNG_BACKGROUND) &&
  1.1056 +       (color_type == PNG_COLOR_TYPE_PALETTE))
  1.1057 +   {
  1.1058 +      int i;
  1.1059 +      int istop = (int)png_ptr->num_trans;
  1.1060 +      png_color back;
  1.1061 +      png_colorp palette = png_ptr->palette;
  1.1062 +
  1.1063 +      back.red   = (png_byte)png_ptr->background.red;
  1.1064 +      back.green = (png_byte)png_ptr->background.green;
  1.1065 +      back.blue  = (png_byte)png_ptr->background.blue;
  1.1066 +
  1.1067 +      for (i = 0; i < istop; i++)
  1.1068 +      {
  1.1069 +         if (png_ptr->trans[i] == 0)
  1.1070 +         {
  1.1071 +            palette[i] = back;
  1.1072 +         }
  1.1073 +         else if (png_ptr->trans[i] != 0xff)
  1.1074 +         {
  1.1075 +            /* The png_composite() macro is defined in png.h */
  1.1076 +            png_composite(palette[i].red, palette[i].red,
  1.1077 +               png_ptr->trans[i], back.red);
  1.1078 +            png_composite(palette[i].green, palette[i].green,
  1.1079 +               png_ptr->trans[i], back.green);
  1.1080 +            png_composite(palette[i].blue, palette[i].blue,
  1.1081 +               png_ptr->trans[i], back.blue);
  1.1082 +         }
  1.1083 +      }
  1.1084 +
  1.1085 +      /* Handled alpha, still need to strip the channel. */
  1.1086 +      png_ptr->transformations &= ~PNG_BACKGROUND;
  1.1087 +      png_ptr->transformations |= PNG_STRIP_ALPHA;
  1.1088 +   }
  1.1089 +#endif /* PNG_READ_BACKGROUND_SUPPORTED */
  1.1090 +
  1.1091 +#if defined(PNG_READ_SHIFT_SUPPORTED)
  1.1092 +   if ((png_ptr->transformations & PNG_SHIFT) &&
  1.1093 +      (color_type == PNG_COLOR_TYPE_PALETTE))
  1.1094 +   {
  1.1095 +      png_uint_16 i;
  1.1096 +      png_uint_16 istop = png_ptr->num_palette;
  1.1097 +      int sr = 8 - png_ptr->sig_bit.red;
  1.1098 +      int sg = 8 - png_ptr->sig_bit.green;
  1.1099 +      int sb = 8 - png_ptr->sig_bit.blue;
  1.1100 +
  1.1101 +      if (sr < 0 || sr > 8)
  1.1102 +         sr = 0;
  1.1103 +      if (sg < 0 || sg > 8)
  1.1104 +         sg = 0;
  1.1105 +      if (sb < 0 || sb > 8)
  1.1106 +         sb = 0;
  1.1107 +      for (i = 0; i < istop; i++)
  1.1108 +      {
  1.1109 +         png_ptr->palette[i].red >>= sr;
  1.1110 +         png_ptr->palette[i].green >>= sg;
  1.1111 +         png_ptr->palette[i].blue >>= sb;
  1.1112 +      }
  1.1113 +   }
  1.1114 +#endif  /* PNG_READ_SHIFT_SUPPORTED */
  1.1115 + }
  1.1116 +#if !defined(PNG_READ_GAMMA_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) \
  1.1117 + && !defined(PNG_READ_BACKGROUND_SUPPORTED)
  1.1118 +   if (png_ptr)
  1.1119 +      return;
  1.1120 +#endif
  1.1121 +}
  1.1122 +
  1.1123 +/* Modify the info structure to reflect the transformations.  The
  1.1124 + * info should be updated so a PNG file could be written with it,
  1.1125 + * assuming the transformations result in valid PNG data.
  1.1126 + */
  1.1127 +void /* PRIVATE */
  1.1128 +png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
  1.1129 +{
  1.1130 +   png_debug(1, "in png_read_transform_info\n");
  1.1131 +#if defined(PNG_READ_EXPAND_SUPPORTED)
  1.1132 +   if (png_ptr->transformations & PNG_EXPAND)
  1.1133 +   {
  1.1134 +      if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
  1.1135 +      {
  1.1136 +         if (png_ptr->num_trans &&
  1.1137 +              (png_ptr->transformations & PNG_EXPAND_tRNS))
  1.1138 +            info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
  1.1139 +         else
  1.1140 +            info_ptr->color_type = PNG_COLOR_TYPE_RGB;
  1.1141 +         info_ptr->bit_depth = 8;
  1.1142 +         info_ptr->num_trans = 0;
  1.1143 +      }
  1.1144 +      else
  1.1145 +      {
  1.1146 +         if (png_ptr->num_trans)
  1.1147 +         {
  1.1148 +            if (png_ptr->transformations & PNG_EXPAND_tRNS)
  1.1149 +              info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
  1.1150 +#if 0 /* Removed from libpng-1.2.27 */
  1.1151 +            else
  1.1152 +              info_ptr->color_type |= PNG_COLOR_MASK_COLOR;
  1.1153 +#endif
  1.1154 +         }
  1.1155 +         if (info_ptr->bit_depth < 8)
  1.1156 +            info_ptr->bit_depth = 8;
  1.1157 +         info_ptr->num_trans = 0;
  1.1158 +      }
  1.1159 +   }
  1.1160 +#endif
  1.1161 +
  1.1162 +#if defined(PNG_READ_BACKGROUND_SUPPORTED)
  1.1163 +   if (png_ptr->transformations & PNG_BACKGROUND)
  1.1164 +   {
  1.1165 +      info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
  1.1166 +      info_ptr->num_trans = 0;
  1.1167 +      info_ptr->background = png_ptr->background;
  1.1168 +   }
  1.1169 +#endif
  1.1170 +
  1.1171 +#if defined(PNG_READ_GAMMA_SUPPORTED)
  1.1172 +   if (png_ptr->transformations & PNG_GAMMA)
  1.1173 +   {
  1.1174 +#ifdef PNG_FLOATING_POINT_SUPPORTED
  1.1175 +      info_ptr->gamma = png_ptr->gamma;
  1.1176 +#endif
  1.1177 +#ifdef PNG_FIXED_POINT_SUPPORTED
  1.1178 +      info_ptr->int_gamma = png_ptr->int_gamma;
  1.1179 +#endif
  1.1180 +   }
  1.1181 +#endif
  1.1182 +
  1.1183 +#if defined(PNG_READ_16_TO_8_SUPPORTED)
  1.1184 +   if ((png_ptr->transformations & PNG_16_TO_8) && (info_ptr->bit_depth == 16))
  1.1185 +      info_ptr->bit_depth = 8;
  1.1186 +#endif
  1.1187 +
  1.1188 +#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
  1.1189 +   if (png_ptr->transformations & PNG_GRAY_TO_RGB)
  1.1190 +      info_ptr->color_type |= PNG_COLOR_MASK_COLOR;
  1.1191 +#endif
  1.1192 +
  1.1193 +#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
  1.1194 +   if (png_ptr->transformations & PNG_RGB_TO_GRAY)
  1.1195 +      info_ptr->color_type &= ~PNG_COLOR_MASK_COLOR;
  1.1196 +#endif
  1.1197 +
  1.1198 +#if defined(PNG_READ_DITHER_SUPPORTED)
  1.1199 +   if (png_ptr->transformations & PNG_DITHER)
  1.1200 +   {
  1.1201 +      if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
  1.1202 +         (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) &&
  1.1203 +         png_ptr->palette_lookup && info_ptr->bit_depth == 8)
  1.1204 +      {
  1.1205 +         info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
  1.1206 +      }
  1.1207 +   }
  1.1208 +#endif
  1.1209 +
  1.1210 +#if defined(PNG_READ_PACK_SUPPORTED)
  1.1211 +   if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8))
  1.1212 +      info_ptr->bit_depth = 8;
  1.1213 +#endif
  1.1214 +
  1.1215 +   if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
  1.1216 +      info_ptr->channels = 1;
  1.1217 +   else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
  1.1218 +      info_ptr->channels = 3;
  1.1219 +   else
  1.1220 +      info_ptr->channels = 1;
  1.1221 +
  1.1222 +#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
  1.1223 +   if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA)
  1.1224 +      info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
  1.1225 +#endif
  1.1226 +
  1.1227 +   if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
  1.1228 +      info_ptr->channels++;
  1.1229 +
  1.1230 +#if defined(PNG_READ_FILLER_SUPPORTED)
  1.1231 +   /* STRIP_ALPHA and FILLER allowed:  MASK_ALPHA bit stripped above */
  1.1232 +   if ((png_ptr->transformations & PNG_FILLER) &&
  1.1233 +       ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
  1.1234 +       (info_ptr->color_type == PNG_COLOR_TYPE_GRAY)))
  1.1235 +   {
  1.1236 +      info_ptr->channels++;
  1.1237 +      /* if adding a true alpha channel not just filler */
  1.1238 +#if !defined(PNG_1_0_X)
  1.1239 +      if (png_ptr->transformations & PNG_ADD_ALPHA)
  1.1240 +        info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
  1.1241 +#endif
  1.1242 +   }
  1.1243 +#endif
  1.1244 +
  1.1245 +#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \
  1.1246 +defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
  1.1247 +   if (png_ptr->transformations & PNG_USER_TRANSFORM)
  1.1248 +     {
  1.1249 +       if (info_ptr->bit_depth < png_ptr->user_transform_depth)
  1.1250 +         info_ptr->bit_depth = png_ptr->user_transform_depth;
  1.1251 +       if (info_ptr->channels < png_ptr->user_transform_channels)
  1.1252 +         info_ptr->channels = png_ptr->user_transform_channels;
  1.1253 +     }
  1.1254 +#endif
  1.1255 +
  1.1256 +   info_ptr->pixel_depth = (png_byte)(info_ptr->channels *
  1.1257 +      info_ptr->bit_depth);
  1.1258 +
  1.1259 +   info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, info_ptr->width);
  1.1260 +
  1.1261 +#if !defined(PNG_READ_EXPAND_SUPPORTED)
  1.1262 +   if (png_ptr)
  1.1263 +      return;
  1.1264 +#endif
  1.1265 +}
  1.1266 +
  1.1267 +/* Transform the row.  The order of transformations is significant,
  1.1268 + * and is very touchy.  If you add a transformation, take care to
  1.1269 + * decide how it fits in with the other transformations here.
  1.1270 + */
  1.1271 +void /* PRIVATE */
  1.1272 +png_do_read_transformations(png_structp png_ptr)
  1.1273 +{
  1.1274 +   png_debug(1, "in png_do_read_transformations\n");
  1.1275 +   if (png_ptr->row_buf == NULL)
  1.1276 +   {
  1.1277 +#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
  1.1278 +      char msg[50];
  1.1279 +
  1.1280 +      png_snprintf2(msg, 50,
  1.1281 +         "NULL row buffer for row %ld, pass %d", (long)png_ptr->row_number,
  1.1282 +         png_ptr->pass);
  1.1283 +      png_error(png_ptr, msg);
  1.1284 +#else
  1.1285 +      png_error(png_ptr, "NULL row buffer");
  1.1286 +#endif
  1.1287 +   }
  1.1288 +#ifdef PNG_WARN_UNINITIALIZED_ROW
  1.1289 +   if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
  1.1290 +      /* Application has failed to call either png_read_start_image()
  1.1291 +       * or png_read_update_info() after setting transforms that expand
  1.1292 +       * pixels.  This check added to libpng-1.2.19 */
  1.1293 +#if (PNG_WARN_UNINITIALIZED_ROW==1)
  1.1294 +      png_error(png_ptr, "Uninitialized row");
  1.1295 +#else
  1.1296 +      png_warning(png_ptr, "Uninitialized row");
  1.1297 +#endif
  1.1298 +#endif
  1.1299 +
  1.1300 +#if defined(PNG_READ_EXPAND_SUPPORTED)
  1.1301 +   if (png_ptr->transformations & PNG_EXPAND)
  1.1302 +   {
  1.1303 +      if (png_ptr->row_info.color_type == PNG_COLOR_TYPE_PALETTE)
  1.1304 +      {
  1.1305 +         png_do_expand_palette(&(png_ptr->row_info), png_ptr->row_buf + 1,
  1.1306 +            png_ptr->palette, png_ptr->trans, png_ptr->num_trans);
  1.1307 +      }
  1.1308 +      else
  1.1309 +      {
  1.1310 +         if (png_ptr->num_trans &&
  1.1311 +             (png_ptr->transformations & PNG_EXPAND_tRNS))
  1.1312 +            png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
  1.1313 +               &(png_ptr->trans_values));
  1.1314 +         else
  1.1315 +            png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
  1.1316 +               NULL);
  1.1317 +      }
  1.1318 +   }
  1.1319 +#endif
  1.1320 +
  1.1321 +#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
  1.1322 +   if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA)
  1.1323 +      png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
  1.1324 +         PNG_FLAG_FILLER_AFTER | (png_ptr->flags & PNG_FLAG_STRIP_ALPHA));
  1.1325 +#endif
  1.1326 +
  1.1327 +#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
  1.1328 +   if (png_ptr->transformations & PNG_RGB_TO_GRAY)
  1.1329 +   {
  1.1330 +      int rgb_error =
  1.1331 +         png_do_rgb_to_gray(png_ptr, &(png_ptr->row_info), png_ptr->row_buf + 1);
  1.1332 +      if (rgb_error)
  1.1333 +      {
  1.1334 +         png_ptr->rgb_to_gray_status=1;
  1.1335 +         if ((png_ptr->transformations & PNG_RGB_TO_GRAY) == 
  1.1336 +             PNG_RGB_TO_GRAY_WARN)
  1.1337 +            png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel");
  1.1338 +         if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
  1.1339 +             PNG_RGB_TO_GRAY_ERR)
  1.1340 +            png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel");
  1.1341 +      }
  1.1342 +   }
  1.1343 +#endif
  1.1344 +
  1.1345 +/*
  1.1346 +From Andreas Dilger e-mail to png-implement, 26 March 1998:
  1.1347 +
  1.1348 +  In most cases, the "simple transparency" should be done prior to doing
  1.1349 +  gray-to-RGB, or you will have to test 3x as many bytes to check if a
  1.1350 +  pixel is transparent.  You would also need to make sure that the
  1.1351 +  transparency information is upgraded to RGB.
  1.1352 +
  1.1353 +  To summarize, the current flow is:
  1.1354 +  - Gray + simple transparency -> compare 1 or 2 gray bytes and composite
  1.1355 +                                  with background "in place" if transparent,
  1.1356 +                                  convert to RGB if necessary
  1.1357 +  - Gray + alpha -> composite with gray background and remove alpha bytes,
  1.1358 +                                  convert to RGB if necessary
  1.1359 +
  1.1360 +  To support RGB backgrounds for gray images we need:
  1.1361 +  - Gray + simple transparency -> convert to RGB + simple transparency, compare
  1.1362 +                                  3 or 6 bytes and composite with background
  1.1363 +                                  "in place" if transparent (3x compare/pixel
  1.1364 +                                  compared to doing composite with gray bkgrnd)
  1.1365 +  - Gray + alpha -> convert to RGB + alpha, composite with background and
  1.1366 +                                  remove alpha bytes (3x float operations/pixel
  1.1367 +                                  compared with composite on gray background)
  1.1368 +
  1.1369 +  Greg's change will do this.  The reason it wasn't done before is for
  1.1370 +  performance, as this increases the per-pixel operations.  If we would check
  1.1371 +  in advance if the background was gray or RGB, and position the gray-to-RGB
  1.1372 +  transform appropriately, then it would save a lot of work/time.
  1.1373 + */
  1.1374 +
  1.1375 +#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
  1.1376 +   /* if gray -> RGB, do so now only if background is non-gray; else do later
  1.1377 +    * for performance reasons */
  1.1378 +   if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
  1.1379 +       !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
  1.1380 +      png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
  1.1381 +#endif
  1.1382 +
  1.1383 +#if defined(PNG_READ_BACKGROUND_SUPPORTED)
  1.1384 +   if ((png_ptr->transformations & PNG_BACKGROUND) &&
  1.1385 +      ((png_ptr->num_trans != 0 ) ||
  1.1386 +      (png_ptr->color_type & PNG_COLOR_MASK_ALPHA)))
  1.1387 +      png_do_background(&(png_ptr->row_info), png_ptr->row_buf + 1,
  1.1388 +         &(png_ptr->trans_values), &(png_ptr->background)
  1.1389 +#if defined(PNG_READ_GAMMA_SUPPORTED)
  1.1390 +         , &(png_ptr->background_1),
  1.1391 +         png_ptr->gamma_table, png_ptr->gamma_from_1,
  1.1392 +         png_ptr->gamma_to_1, png_ptr->gamma_16_table,
  1.1393 +         png_ptr->gamma_16_from_1, png_ptr->gamma_16_to_1,
  1.1394 +         png_ptr->gamma_shift
  1.1395 +#endif
  1.1396 +);
  1.1397 +#endif
  1.1398 +
  1.1399 +#if defined(PNG_READ_GAMMA_SUPPORTED)
  1.1400 +   if ((png_ptr->transformations & PNG_GAMMA) &&
  1.1401 +#if defined(PNG_READ_BACKGROUND_SUPPORTED)
  1.1402 +      !((png_ptr->transformations & PNG_BACKGROUND) &&
  1.1403 +      ((png_ptr->num_trans != 0) ||
  1.1404 +      (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) &&
  1.1405 +#endif
  1.1406 +      (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE))
  1.1407 +      png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1,
  1.1408 +         png_ptr->gamma_table, png_ptr->gamma_16_table,
  1.1409 +         png_ptr->gamma_shift);
  1.1410 +#endif
  1.1411 +
  1.1412 +#if defined(PNG_READ_16_TO_8_SUPPORTED)
  1.1413 +   if (png_ptr->transformations & PNG_16_TO_8)
  1.1414 +      png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1);
  1.1415 +#endif
  1.1416 +
  1.1417 +#if defined(PNG_READ_DITHER_SUPPORTED)
  1.1418 +   if (png_ptr->transformations & PNG_DITHER)
  1.1419 +   {
  1.1420 +      png_do_dither((png_row_infop)&(png_ptr->row_info), png_ptr->row_buf + 1,
  1.1421 +         png_ptr->palette_lookup, png_ptr->dither_index);
  1.1422 +      if (png_ptr->row_info.rowbytes == (png_uint_32)0)
  1.1423 +         png_error(png_ptr, "png_do_dither returned rowbytes=0");
  1.1424 +   }
  1.1425 +#endif
  1.1426 +
  1.1427 +#if defined(PNG_READ_INVERT_SUPPORTED)
  1.1428 +   if (png_ptr->transformations & PNG_INVERT_MONO)
  1.1429 +      png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1);
  1.1430 +#endif
  1.1431 +
  1.1432 +#if defined(PNG_READ_SHIFT_SUPPORTED)
  1.1433 +   if (png_ptr->transformations & PNG_SHIFT)
  1.1434 +      png_do_unshift(&(png_ptr->row_info), png_ptr->row_buf + 1,
  1.1435 +         &(png_ptr->shift));
  1.1436 +#endif
  1.1437 +
  1.1438 +#if defined(PNG_READ_PACK_SUPPORTED)
  1.1439 +   if (png_ptr->transformations & PNG_PACK)
  1.1440 +      png_do_unpack(&(png_ptr->row_info), png_ptr->row_buf + 1);
  1.1441 +#endif
  1.1442 +
  1.1443 +#if defined(PNG_READ_BGR_SUPPORTED)
  1.1444 +   if (png_ptr->transformations & PNG_BGR)
  1.1445 +      png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1);
  1.1446 +#endif
  1.1447 +
  1.1448 +#if defined(PNG_READ_PACKSWAP_SUPPORTED)
  1.1449 +   if (png_ptr->transformations & PNG_PACKSWAP)
  1.1450 +      png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1);
  1.1451 +#endif
  1.1452 +
  1.1453 +#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
  1.1454 +   /* if gray -> RGB, do so now only if we did not do so above */
  1.1455 +   if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
  1.1456 +       (png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
  1.1457 +      png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
  1.1458 +#endif
  1.1459 +
  1.1460 +#if defined(PNG_READ_FILLER_SUPPORTED)
  1.1461 +   if (png_ptr->transformations & PNG_FILLER)
  1.1462 +      png_do_read_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
  1.1463 +         (png_uint_32)png_ptr->filler, png_ptr->flags);
  1.1464 +#endif
  1.1465 +
  1.1466 +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
  1.1467 +   if (png_ptr->transformations & PNG_INVERT_ALPHA)
  1.1468 +      png_do_read_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
  1.1469 +#endif
  1.1470 +
  1.1471 +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
  1.1472 +   if (png_ptr->transformations & PNG_SWAP_ALPHA)
  1.1473 +      png_do_read_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
  1.1474 +#endif
  1.1475 +
  1.1476 +#if defined(PNG_READ_SWAP_SUPPORTED)
  1.1477 +   if (png_ptr->transformations & PNG_SWAP_BYTES)
  1.1478 +      png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1);
  1.1479 +#endif
  1.1480 +
  1.1481 +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
  1.1482 +   if (png_ptr->transformations & PNG_USER_TRANSFORM)
  1.1483 +    {
  1.1484 +      if (png_ptr->read_user_transform_fn != NULL)
  1.1485 +        (*(png_ptr->read_user_transform_fn)) /* user read transform function */
  1.1486 +          (png_ptr,                    /* png_ptr */
  1.1487 +           &(png_ptr->row_info),       /* row_info:     */
  1.1488 +             /*  png_uint_32 width;          width of row */
  1.1489 +             /*  png_uint_32 rowbytes;       number of bytes in row */
  1.1490 +             /*  png_byte color_type;        color type of pixels */
  1.1491 +             /*  png_byte bit_depth;         bit depth of samples */
  1.1492 +             /*  png_byte channels;          number of channels (1-4) */
  1.1493 +             /*  png_byte pixel_depth;       bits per pixel (depth*channels) */
  1.1494 +           png_ptr->row_buf + 1);      /* start of pixel data for row */
  1.1495 +#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
  1.1496 +      if (png_ptr->user_transform_depth)
  1.1497 +         png_ptr->row_info.bit_depth = png_ptr->user_transform_depth;
  1.1498 +      if (png_ptr->user_transform_channels)
  1.1499 +         png_ptr->row_info.channels = png_ptr->user_transform_channels;
  1.1500 +#endif
  1.1501 +      png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth *
  1.1502 +         png_ptr->row_info.channels);
  1.1503 +      png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth,
  1.1504 +         png_ptr->row_info.width);
  1.1505 +   }
  1.1506 +#endif
  1.1507 +
  1.1508 +}
  1.1509 +
  1.1510 +#if defined(PNG_READ_PACK_SUPPORTED)
  1.1511 +/* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel,
  1.1512 + * without changing the actual values.  Thus, if you had a row with
  1.1513 + * a bit depth of 1, you would end up with bytes that only contained
  1.1514 + * the numbers 0 or 1.  If you would rather they contain 0 and 255, use
  1.1515 + * png_do_shift() after this.
  1.1516 + */
  1.1517 +void /* PRIVATE */
  1.1518 +png_do_unpack(png_row_infop row_info, png_bytep row)
  1.1519 +{
  1.1520 +   png_debug(1, "in png_do_unpack\n");
  1.1521 +#if defined(PNG_USELESS_TESTS_SUPPORTED)
  1.1522 +   if (row != NULL && row_info != NULL && row_info->bit_depth < 8)
  1.1523 +#else
  1.1524 +   if (row_info->bit_depth < 8)
  1.1525 +#endif
  1.1526 +   {
  1.1527 +      png_uint_32 i;
  1.1528 +      png_uint_32 row_width=row_info->width;
  1.1529 +
  1.1530 +      switch (row_info->bit_depth)
  1.1531 +      {
  1.1532 +         case 1:
  1.1533 +         {
  1.1534 +            png_bytep sp = row + (png_size_t)((row_width - 1) >> 3);
  1.1535 +            png_bytep dp = row + (png_size_t)row_width - 1;
  1.1536 +            png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07);
  1.1537 +            for (i = 0; i < row_width; i++)
  1.1538 +            {
  1.1539 +               *dp = (png_byte)((*sp >> shift) & 0x01);
  1.1540 +               if (shift == 7)
  1.1541 +               {
  1.1542 +                  shift = 0;
  1.1543 +                  sp--;
  1.1544 +               }
  1.1545 +               else
  1.1546 +                  shift++;
  1.1547 +
  1.1548 +               dp--;
  1.1549 +            }
  1.1550 +            break;
  1.1551 +         }
  1.1552 +         case 2:
  1.1553 +         {
  1.1554 +
  1.1555 +            png_bytep sp = row + (png_size_t)((row_width - 1) >> 2);
  1.1556 +            png_bytep dp = row + (png_size_t)row_width - 1;
  1.1557 +            png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
  1.1558 +            for (i = 0; i < row_width; i++)
  1.1559 +            {
  1.1560 +               *dp = (png_byte)((*sp >> shift) & 0x03);
  1.1561 +               if (shift == 6)
  1.1562 +               {
  1.1563 +                  shift = 0;
  1.1564 +                  sp--;
  1.1565 +               }
  1.1566 +               else
  1.1567 +                  shift += 2;
  1.1568 +
  1.1569 +               dp--;
  1.1570 +            }
  1.1571 +            break;
  1.1572 +         }
  1.1573 +         case 4:
  1.1574 +         {
  1.1575 +            png_bytep sp = row + (png_size_t)((row_width - 1) >> 1);
  1.1576 +            png_bytep dp = row + (png_size_t)row_width - 1;
  1.1577 +            png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
  1.1578 +            for (i = 0; i < row_width; i++)
  1.1579 +            {
  1.1580 +               *dp = (png_byte)((*sp >> shift) & 0x0f);
  1.1581 +               if (shift == 4)
  1.1582 +               {
  1.1583 +                  shift = 0;
  1.1584 +                  sp--;
  1.1585 +               }
  1.1586 +               else
  1.1587 +                  shift = 4;
  1.1588 +
  1.1589 +               dp--;
  1.1590 +            }
  1.1591 +            break;
  1.1592 +         }
  1.1593 +      }
  1.1594 +      row_info->bit_depth = 8;
  1.1595 +      row_info->pixel_depth = (png_byte)(8 * row_info->channels);
  1.1596 +      row_info->rowbytes = row_width * row_info->channels;
  1.1597 +   }
  1.1598 +}
  1.1599 +#endif
  1.1600 +
  1.1601 +#if defined(PNG_READ_SHIFT_SUPPORTED)
  1.1602 +/* Reverse the effects of png_do_shift.  This routine merely shifts the
  1.1603 + * pixels back to their significant bits values.  Thus, if you have
  1.1604 + * a row of bit depth 8, but only 5 are significant, this will shift
  1.1605 + * the values back to 0 through 31.
  1.1606 + */
  1.1607 +void /* PRIVATE */
  1.1608 +png_do_unshift(png_row_infop row_info, png_bytep row, png_color_8p sig_bits)
  1.1609 +{
  1.1610 +   png_debug(1, "in png_do_unshift\n");
  1.1611 +   if (
  1.1612 +#if defined(PNG_USELESS_TESTS_SUPPORTED)
  1.1613 +       row != NULL && row_info != NULL && sig_bits != NULL &&
  1.1614 +#endif
  1.1615 +       row_info->color_type != PNG_COLOR_TYPE_PALETTE)
  1.1616 +   {
  1.1617 +      int shift[4];
  1.1618 +      int channels = 0;
  1.1619 +      int c;
  1.1620 +      png_uint_16 value = 0;
  1.1621 +      png_uint_32 row_width = row_info->width;
  1.1622 +
  1.1623 +      if (row_info->color_type & PNG_COLOR_MASK_COLOR)
  1.1624 +      {
  1.1625 +         shift[channels++] = row_info->bit_depth - sig_bits->red;
  1.1626 +         shift[channels++] = row_info->bit_depth - sig_bits->green;
  1.1627 +         shift[channels++] = row_info->bit_depth - sig_bits->blue;
  1.1628 +      }
  1.1629 +      else
  1.1630 +      {
  1.1631 +         shift[channels++] = row_info->bit_depth - sig_bits->gray;
  1.1632 +      }
  1.1633 +      if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
  1.1634 +      {
  1.1635 +         shift[channels++] = row_info->bit_depth - sig_bits->alpha;
  1.1636 +      }
  1.1637 +
  1.1638 +      for (c = 0; c < channels; c++)
  1.1639 +      {
  1.1640 +         if (shift[c] <= 0)
  1.1641 +            shift[c] = 0;
  1.1642 +         else
  1.1643 +            value = 1;
  1.1644 +      }
  1.1645 +
  1.1646 +      if (!value)
  1.1647 +         return;
  1.1648 +
  1.1649 +      switch (row_info->bit_depth)
  1.1650 +      {
  1.1651 +         case 2:
  1.1652 +         {
  1.1653 +            png_bytep bp;
  1.1654 +            png_uint_32 i;
  1.1655 +            png_uint_32 istop = row_info->rowbytes;
  1.1656 +
  1.1657 +            for (bp = row, i = 0; i < istop; i++)
  1.1658 +            {
  1.1659 +               *bp >>= 1;
  1.1660 +               *bp++ &= 0x55;
  1.1661 +            }
  1.1662 +            break;
  1.1663 +         }
  1.1664 +         case 4:
  1.1665 +         {
  1.1666 +            png_bytep bp = row;
  1.1667 +            png_uint_32 i;
  1.1668 +            png_uint_32 istop = row_info->rowbytes;
  1.1669 +            png_byte mask = (png_byte)((((int)0xf0 >> shift[0]) & (int)0xf0) |
  1.1670 +               (png_byte)((int)0xf >> shift[0]));
  1.1671 +
  1.1672 +            for (i = 0; i < istop; i++)
  1.1673 +            {
  1.1674 +               *bp >>= shift[0];
  1.1675 +               *bp++ &= mask;
  1.1676 +            }
  1.1677 +            break;
  1.1678 +         }
  1.1679 +         case 8:
  1.1680 +         {
  1.1681 +            png_bytep bp = row;
  1.1682 +            png_uint_32 i;
  1.1683 +            png_uint_32 istop = row_width * channels;
  1.1684 +
  1.1685 +            for (i = 0; i < istop; i++)
  1.1686 +            {
  1.1687 +               *bp++ >>= shift[i%channels];
  1.1688 +            }
  1.1689 +            break;
  1.1690 +         }
  1.1691 +         case 16:
  1.1692 +         {
  1.1693 +            png_bytep bp = row;
  1.1694 +            png_uint_32 i;
  1.1695 +            png_uint_32 istop = channels * row_width;
  1.1696 +
  1.1697 +            for (i = 0; i < istop; i++)
  1.1698 +            {
  1.1699 +               value = (png_uint_16)((*bp << 8) + *(bp + 1));
  1.1700 +               value >>= shift[i%channels];
  1.1701 +               *bp++ = (png_byte)(value >> 8);
  1.1702 +               *bp++ = (png_byte)(value & 0xff);
  1.1703 +            }
  1.1704 +            break;
  1.1705 +         }
  1.1706 +      }
  1.1707 +   }
  1.1708 +}
  1.1709 +#endif
  1.1710 +
  1.1711 +#if defined(PNG_READ_16_TO_8_SUPPORTED)
  1.1712 +/* chop rows of bit depth 16 down to 8 */
  1.1713 +void /* PRIVATE */
  1.1714 +png_do_chop(png_row_infop row_info, png_bytep row)
  1.1715 +{
  1.1716 +   png_debug(1, "in png_do_chop\n");
  1.1717 +#if defined(PNG_USELESS_TESTS_SUPPORTED)
  1.1718 +   if (row != NULL && row_info != NULL && row_info->bit_depth == 16)
  1.1719 +#else
  1.1720 +   if (row_info->bit_depth == 16)
  1.1721 +#endif
  1.1722 +   {
  1.1723 +      png_bytep sp = row;
  1.1724 +      png_bytep dp = row;
  1.1725 +      png_uint_32 i;
  1.1726 +      png_uint_32 istop = row_info->width * row_info->channels;
  1.1727 +
  1.1728 +      for (i = 0; i<istop; i++, sp += 2, dp++)
  1.1729 +      {
  1.1730 +#if defined(PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED)
  1.1731 +      /* This does a more accurate scaling of the 16-bit color
  1.1732 +       * value, rather than a simple low-byte truncation.
  1.1733 +       *
  1.1734 +       * What the ideal calculation should be:
  1.1735 +       *   *dp = (((((png_uint_32)(*sp) << 8) |
  1.1736 +       *          (png_uint_32)(*(sp + 1))) * 255 + 127) / (png_uint_32)65535L;
  1.1737 +       *
  1.1738 +       * GRR: no, I think this is what it really should be:
  1.1739 +       *   *dp = (((((png_uint_32)(*sp) << 8) |
  1.1740 +       *           (png_uint_32)(*(sp + 1))) + 128L) / (png_uint_32)257L;
  1.1741 +       *
  1.1742 +       * GRR: here's the exact calculation with shifts:
  1.1743 +       *   temp = (((png_uint_32)(*sp) << 8) | (png_uint_32)(*(sp + 1))) + 128L;
  1.1744 +       *   *dp = (temp - (temp >> 8)) >> 8;
  1.1745 +       *
  1.1746 +       * Approximate calculation with shift/add instead of multiply/divide:
  1.1747 +       *   *dp = ((((png_uint_32)(*sp) << 8) |
  1.1748 +       *          (png_uint_32)((int)(*(sp + 1)) - *sp)) + 128) >> 8;
  1.1749 +       *
  1.1750 +       * What we actually do to avoid extra shifting and conversion:
  1.1751 +       */
  1.1752 +
  1.1753 +         *dp = *sp + ((((int)(*(sp + 1)) - *sp) > 128) ? 1 : 0);
  1.1754 +#else
  1.1755 +       /* Simply discard the low order byte */
  1.1756 +         *dp = *sp;
  1.1757 +#endif
  1.1758 +      }
  1.1759 +      row_info->bit_depth = 8;
  1.1760 +      row_info->pixel_depth = (png_byte)(8 * row_info->channels);
  1.1761 +      row_info->rowbytes = row_info->width * row_info->channels;
  1.1762 +   }
  1.1763 +}
  1.1764 +#endif
  1.1765 +
  1.1766 +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
  1.1767 +void /* PRIVATE */
  1.1768 +png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
  1.1769 +{
  1.1770 +   png_debug(1, "in png_do_read_swap_alpha\n");
  1.1771 +#if defined(PNG_USELESS_TESTS_SUPPORTED)
  1.1772 +   if (row != NULL && row_info != NULL)
  1.1773 +#endif
  1.1774 +   {
  1.1775 +      png_uint_32 row_width = row_info->width;
  1.1776 +      if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
  1.1777 +      {
  1.1778 +         /* This converts from RGBA to ARGB */
  1.1779 +         if (row_info->bit_depth == 8)
  1.1780 +         {
  1.1781 +            png_bytep sp = row + row_info->rowbytes;
  1.1782 +            png_bytep dp = sp;
  1.1783 +            png_byte save;
  1.1784 +            png_uint_32 i;
  1.1785 +
  1.1786 +            for (i = 0; i < row_width; i++)
  1.1787 +            {
  1.1788 +               save = *(--sp);
  1.1789 +               *(--dp) = *(--sp);
  1.1790 +               *(--dp) = *(--sp);
  1.1791 +               *(--dp) = *(--sp);
  1.1792 +               *(--dp) = save;
  1.1793 +            }
  1.1794 +         }
  1.1795 +         /* This converts from RRGGBBAA to AARRGGBB */
  1.1796 +         else
  1.1797 +         {
  1.1798 +            png_bytep sp = row + row_info->rowbytes;
  1.1799 +            png_bytep dp = sp;
  1.1800 +            png_byte save[2];
  1.1801 +            png_uint_32 i;
  1.1802 +
  1.1803 +            for (i = 0; i < row_width; i++)
  1.1804 +            {
  1.1805 +               save[0] = *(--sp);
  1.1806 +               save[1] = *(--sp);
  1.1807 +               *(--dp) = *(--sp);
  1.1808 +               *(--dp) = *(--sp);
  1.1809 +               *(--dp) = *(--sp);
  1.1810 +               *(--dp) = *(--sp);
  1.1811 +               *(--dp) = *(--sp);
  1.1812 +               *(--dp) = *(--sp);
  1.1813 +               *(--dp) = save[0];
  1.1814 +               *(--dp) = save[1];
  1.1815 +            }
  1.1816 +         }
  1.1817 +      }
  1.1818 +      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
  1.1819 +      {
  1.1820 +         /* This converts from GA to AG */
  1.1821 +         if (row_info->bit_depth == 8)
  1.1822 +         {
  1.1823 +            png_bytep sp = row + row_info->rowbytes;
  1.1824 +            png_bytep dp = sp;
  1.1825 +            png_byte save;
  1.1826 +            png_uint_32 i;
  1.1827 +
  1.1828 +            for (i = 0; i < row_width; i++)
  1.1829 +            {
  1.1830 +               save = *(--sp);
  1.1831 +               *(--dp) = *(--sp);
  1.1832 +               *(--dp) = save;
  1.1833 +            }
  1.1834 +         }
  1.1835 +         /* This converts from GGAA to AAGG */
  1.1836 +         else
  1.1837 +         {
  1.1838 +            png_bytep sp = row + row_info->rowbytes;
  1.1839 +            png_bytep dp = sp;
  1.1840 +            png_byte save[2];
  1.1841 +            png_uint_32 i;
  1.1842 +
  1.1843 +            for (i = 0; i < row_width; i++)
  1.1844 +            {
  1.1845 +               save[0] = *(--sp);
  1.1846 +               save[1] = *(--sp);
  1.1847 +               *(--dp) = *(--sp);
  1.1848 +               *(--dp) = *(--sp);
  1.1849 +               *(--dp) = save[0];
  1.1850 +               *(--dp) = save[1];
  1.1851 +            }
  1.1852 +         }
  1.1853 +      }
  1.1854 +   }
  1.1855 +}
  1.1856 +#endif
  1.1857 +
  1.1858 +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
  1.1859 +void /* PRIVATE */
  1.1860 +png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
  1.1861 +{
  1.1862 +   png_debug(1, "in png_do_read_invert_alpha\n");
  1.1863 +#if defined(PNG_USELESS_TESTS_SUPPORTED)
  1.1864 +   if (row != NULL && row_info != NULL)
  1.1865 +#endif
  1.1866 +   {
  1.1867 +      png_uint_32 row_width = row_info->width;
  1.1868 +      if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
  1.1869 +      {
  1.1870 +         /* This inverts the alpha channel in RGBA */
  1.1871 +         if (row_info->bit_depth == 8)
  1.1872 +         {
  1.1873 +            png_bytep sp = row + row_info->rowbytes;
  1.1874 +            png_bytep dp = sp;
  1.1875 +            png_uint_32 i;
  1.1876 +
  1.1877 +            for (i = 0; i < row_width; i++)
  1.1878 +            {
  1.1879 +               *(--dp) = (png_byte)(255 - *(--sp));
  1.1880 +
  1.1881 +/*             This does nothing:
  1.1882 +               *(--dp) = *(--sp);
  1.1883 +               *(--dp) = *(--sp);
  1.1884 +               *(--dp) = *(--sp);
  1.1885 +               We can replace it with:
  1.1886 +*/
  1.1887 +               sp-=3;
  1.1888 +               dp=sp;
  1.1889 +            }
  1.1890 +         }
  1.1891 +         /* This inverts the alpha channel in RRGGBBAA */
  1.1892 +         else
  1.1893 +         {
  1.1894 +            png_bytep sp = row + row_info->rowbytes;
  1.1895 +            png_bytep dp = sp;
  1.1896 +            png_uint_32 i;
  1.1897 +
  1.1898 +            for (i = 0; i < row_width; i++)
  1.1899 +            {
  1.1900 +               *(--dp) = (png_byte)(255 - *(--sp));
  1.1901 +               *(--dp) = (png_byte)(255 - *(--sp));
  1.1902 +
  1.1903 +/*             This does nothing:
  1.1904 +               *(--dp) = *(--sp);
  1.1905 +               *(--dp) = *(--sp);
  1.1906 +               *(--dp) = *(--sp);
  1.1907 +               *(--dp) = *(--sp);
  1.1908 +               *(--dp) = *(--sp);
  1.1909 +               *(--dp) = *(--sp);
  1.1910 +               We can replace it with:
  1.1911 +*/
  1.1912 +               sp-=6;
  1.1913 +               dp=sp;
  1.1914 +            }
  1.1915 +         }
  1.1916 +      }
  1.1917 +      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
  1.1918 +      {
  1.1919 +         /* This inverts the alpha channel in GA */
  1.1920 +         if (row_info->bit_depth == 8)
  1.1921 +         {
  1.1922 +            png_bytep sp = row + row_info->rowbytes;
  1.1923 +            png_bytep dp = sp;
  1.1924 +            png_uint_32 i;
  1.1925 +
  1.1926 +            for (i = 0; i < row_width; i++)
  1.1927 +            {
  1.1928 +               *(--dp) = (png_byte)(255 - *(--sp));
  1.1929 +               *(--dp) = *(--sp);
  1.1930 +            }
  1.1931 +         }
  1.1932 +         /* This inverts the alpha channel in GGAA */
  1.1933 +         else
  1.1934 +         {
  1.1935 +            png_bytep sp  = row + row_info->rowbytes;
  1.1936 +            png_bytep dp = sp;
  1.1937 +            png_uint_32 i;
  1.1938 +
  1.1939 +            for (i = 0; i < row_width; i++)
  1.1940 +            {
  1.1941 +               *(--dp) = (png_byte)(255 - *(--sp));
  1.1942 +               *(--dp) = (png_byte)(255 - *(--sp));
  1.1943 +/*
  1.1944 +               *(--dp) = *(--sp);
  1.1945 +               *(--dp) = *(--sp);
  1.1946 +*/
  1.1947 +               sp-=2;
  1.1948 +               dp=sp;
  1.1949 +            }
  1.1950 +         }
  1.1951 +      }
  1.1952 +   }
  1.1953 +}
  1.1954 +#endif
  1.1955 +
  1.1956 +#if defined(PNG_READ_FILLER_SUPPORTED)
  1.1957 +/* Add filler channel if we have RGB color */
  1.1958 +void /* PRIVATE */
  1.1959 +png_do_read_filler(png_row_infop row_info, png_bytep row,
  1.1960 +   png_uint_32 filler, png_uint_32 flags)
  1.1961 +{
  1.1962 +   png_uint_32 i;
  1.1963 +   png_uint_32 row_width = row_info->width;
  1.1964 +
  1.1965 +   png_byte hi_filler = (png_byte)((filler>>8) & 0xff);
  1.1966 +   png_byte lo_filler = (png_byte)(filler & 0xff);
  1.1967 +
  1.1968 +   png_debug(1, "in png_do_read_filler\n");
  1.1969 +   if (
  1.1970 +#if defined(PNG_USELESS_TESTS_SUPPORTED)
  1.1971 +       row != NULL  && row_info != NULL &&
  1.1972 +#endif
  1.1973 +       row_info->color_type == PNG_COLOR_TYPE_GRAY)
  1.1974 +   {
  1.1975 +      if (row_info->bit_depth == 8)
  1.1976 +      {
  1.1977 +         /* This changes the data from G to GX */
  1.1978 +         if (flags & PNG_FLAG_FILLER_AFTER)
  1.1979 +         {
  1.1980 +            png_bytep sp = row + (png_size_t)row_width;
  1.1981 +            png_bytep dp =  sp + (png_size_t)row_width;
  1.1982 +            for (i = 1; i < row_width; i++)
  1.1983 +            {
  1.1984 +               *(--dp) = lo_filler;
  1.1985 +               *(--dp) = *(--sp);
  1.1986 +            }
  1.1987 +            *(--dp) = lo_filler;
  1.1988 +            row_info->channels = 2;
  1.1989 +            row_info->pixel_depth = 16;
  1.1990 +            row_info->rowbytes = row_width * 2;
  1.1991 +         }
  1.1992 +      /* This changes the data from G to XG */
  1.1993 +         else
  1.1994 +         {
  1.1995 +            png_bytep sp = row + (png_size_t)row_width;
  1.1996 +            png_bytep dp = sp  + (png_size_t)row_width;
  1.1997 +            for (i = 0; i < row_width; i++)
  1.1998 +            {
  1.1999 +               *(--dp) = *(--sp);
  1.2000 +               *(--dp) = lo_filler;
  1.2001 +            }
  1.2002 +            row_info->channels = 2;
  1.2003 +            row_info->pixel_depth = 16;
  1.2004 +            row_info->rowbytes = row_width * 2;
  1.2005 +         }
  1.2006 +      }
  1.2007 +      else if (row_info->bit_depth == 16)
  1.2008 +      {
  1.2009 +         /* This changes the data from GG to GGXX */
  1.2010 +         if (flags & PNG_FLAG_FILLER_AFTER)
  1.2011 +         {
  1.2012 +            png_bytep sp = row + (png_size_t)row_width * 2;
  1.2013 +            png_bytep dp = sp  + (png_size_t)row_width * 2;
  1.2014 +            for (i = 1; i < row_width; i++)
  1.2015 +            {
  1.2016 +               *(--dp) = hi_filler;
  1.2017 +               *(--dp) = lo_filler;
  1.2018 +               *(--dp) = *(--sp);
  1.2019 +               *(--dp) = *(--sp);
  1.2020 +            }
  1.2021 +            *(--dp) = hi_filler;
  1.2022 +            *(--dp) = lo_filler;
  1.2023 +            row_info->channels = 2;
  1.2024 +            row_info->pixel_depth = 32;
  1.2025 +            row_info->rowbytes = row_width * 4;
  1.2026 +         }
  1.2027 +         /* This changes the data from GG to XXGG */
  1.2028 +         else
  1.2029 +         {
  1.2030 +            png_bytep sp = row + (png_size_t)row_width * 2;
  1.2031 +            png_bytep dp = sp  + (png_size_t)row_width * 2;
  1.2032 +            for (i = 0; i < row_width; i++)
  1.2033 +            {
  1.2034 +               *(--dp) = *(--sp);
  1.2035 +               *(--dp) = *(--sp);
  1.2036 +               *(--dp) = hi_filler;
  1.2037 +               *(--dp) = lo_filler;
  1.2038 +            }
  1.2039 +            row_info->channels = 2;
  1.2040 +            row_info->pixel_depth = 32;
  1.2041 +            row_info->rowbytes = row_width * 4;
  1.2042 +         }
  1.2043 +      }
  1.2044 +   } /* COLOR_TYPE == GRAY */
  1.2045 +   else if (row_info->color_type == PNG_COLOR_TYPE_RGB)
  1.2046 +   {
  1.2047 +      if (row_info->bit_depth == 8)
  1.2048 +      {
  1.2049 +         /* This changes the data from RGB to RGBX */
  1.2050 +         if (flags & PNG_FLAG_FILLER_AFTER)
  1.2051 +         {
  1.2052 +            png_bytep sp = row + (png_size_t)row_width * 3;
  1.2053 +            png_bytep dp = sp  + (png_size_t)row_width;
  1.2054 +            for (i = 1; i < row_width; i++)
  1.2055 +            {
  1.2056 +               *(--dp) = lo_filler;
  1.2057 +               *(--dp) = *(--sp);
  1.2058 +               *(--dp) = *(--sp);
  1.2059 +               *(--dp) = *(--sp);
  1.2060 +            }
  1.2061 +            *(--dp) = lo_filler;
  1.2062 +            row_info->channels = 4;
  1.2063 +            row_info->pixel_depth = 32;
  1.2064 +            row_info->rowbytes = row_width * 4;
  1.2065 +         }
  1.2066 +      /* This changes the data from RGB to XRGB */
  1.2067 +         else
  1.2068 +         {
  1.2069 +            png_bytep sp = row + (png_size_t)row_width * 3;
  1.2070 +            png_bytep dp = sp + (png_size_t)row_width;
  1.2071 +            for (i = 0; i < row_width; i++)
  1.2072 +            {
  1.2073 +               *(--dp) = *(--sp);
  1.2074 +               *(--dp) = *(--sp);
  1.2075 +               *(--dp) = *(--sp);
  1.2076 +               *(--dp) = lo_filler;
  1.2077 +            }
  1.2078 +            row_info->channels = 4;
  1.2079 +            row_info->pixel_depth = 32;
  1.2080 +            row_info->rowbytes = row_width * 4;
  1.2081 +         }
  1.2082 +      }
  1.2083 +      else if (row_info->bit_depth == 16)
  1.2084 +      {
  1.2085 +         /* This changes the data from RRGGBB to RRGGBBXX */
  1.2086 +         if (flags & PNG_FLAG_FILLER_AFTER)
  1.2087 +         {
  1.2088 +            png_bytep sp = row + (png_size_t)row_width * 6;
  1.2089 +            png_bytep dp = sp  + (png_size_t)row_width * 2;
  1.2090 +            for (i = 1; i < row_width; i++)
  1.2091 +            {
  1.2092 +               *(--dp) = hi_filler;
  1.2093 +               *(--dp) = lo_filler;
  1.2094 +               *(--dp) = *(--sp);
  1.2095 +               *(--dp) = *(--sp);
  1.2096 +               *(--dp) = *(--sp);
  1.2097 +               *(--dp) = *(--sp);
  1.2098 +               *(--dp) = *(--sp);
  1.2099 +               *(--dp) = *(--sp);
  1.2100 +            }
  1.2101 +            *(--dp) = hi_filler;
  1.2102 +            *(--dp) = lo_filler;
  1.2103 +            row_info->channels = 4;
  1.2104 +            row_info->pixel_depth = 64;
  1.2105 +            row_info->rowbytes = row_width * 8;
  1.2106 +         }
  1.2107 +         /* This changes the data from RRGGBB to XXRRGGBB */
  1.2108 +         else
  1.2109 +         {
  1.2110 +            png_bytep sp = row + (png_size_t)row_width * 6;
  1.2111 +            png_bytep dp = sp  + (png_size_t)row_width * 2;
  1.2112 +            for (i = 0; i < row_width; i++)
  1.2113 +            {
  1.2114 +               *(--dp) = *(--sp);
  1.2115 +               *(--dp) = *(--sp);
  1.2116 +               *(--dp) = *(--sp);
  1.2117 +               *(--dp) = *(--sp);
  1.2118 +               *(--dp) = *(--sp);
  1.2119 +               *(--dp) = *(--sp);
  1.2120 +               *(--dp) = hi_filler;
  1.2121 +               *(--dp) = lo_filler;
  1.2122 +            }
  1.2123 +            row_info->channels = 4;
  1.2124 +            row_info->pixel_depth = 64;
  1.2125 +            row_info->rowbytes = row_width * 8;
  1.2126 +         }
  1.2127 +      }
  1.2128 +   } /* COLOR_TYPE == RGB */
  1.2129 +}
  1.2130 +#endif
  1.2131 +
  1.2132 +#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
  1.2133 +/* expand grayscale files to RGB, with or without alpha */
  1.2134 +void /* PRIVATE */
  1.2135 +png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
  1.2136 +{
  1.2137 +   png_uint_32 i;
  1.2138 +   png_uint_32 row_width = row_info->width;
  1.2139 +
  1.2140 +   png_debug(1, "in png_do_gray_to_rgb\n");
  1.2141 +   if (row_info->bit_depth >= 8 &&
  1.2142 +#if defined(PNG_USELESS_TESTS_SUPPORTED)
  1.2143 +       row != NULL && row_info != NULL &&
  1.2144 +#endif
  1.2145 +      !(row_info->color_type & PNG_COLOR_MASK_COLOR))
  1.2146 +   {
  1.2147 +      if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
  1.2148 +      {
  1.2149 +         if (row_info->bit_depth == 8)
  1.2150 +         {
  1.2151 +            png_bytep sp = row + (png_size_t)row_width - 1;
  1.2152 +            png_bytep dp = sp  + (png_size_t)row_width * 2;
  1.2153 +            for (i = 0; i < row_width; i++)
  1.2154 +            {
  1.2155 +               *(dp--) = *sp;
  1.2156 +               *(dp--) = *sp;
  1.2157 +               *(dp--) = *(sp--);
  1.2158 +            }
  1.2159 +         }
  1.2160 +         else
  1.2161 +         {
  1.2162 +            png_bytep sp = row + (png_size_t)row_width * 2 - 1;
  1.2163 +            png_bytep dp = sp  + (png_size_t)row_width * 4;
  1.2164 +            for (i = 0; i < row_width; i++)
  1.2165 +            {
  1.2166 +               *(dp--) = *sp;
  1.2167 +               *(dp--) = *(sp - 1);
  1.2168 +               *(dp--) = *sp;
  1.2169 +               *(dp--) = *(sp - 1);
  1.2170 +               *(dp--) = *(sp--);
  1.2171 +               *(dp--) = *(sp--);
  1.2172 +            }
  1.2173 +         }
  1.2174 +      }
  1.2175 +      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
  1.2176 +      {
  1.2177 +         if (row_info->bit_depth == 8)
  1.2178 +         {
  1.2179 +            png_bytep sp = row + (png_size_t)row_width * 2 - 1;
  1.2180 +            png_bytep dp = sp  + (png_size_t)row_width * 2;
  1.2181 +            for (i = 0; i < row_width; i++)
  1.2182 +            {
  1.2183 +               *(dp--) = *(sp--);
  1.2184 +               *(dp--) = *sp;
  1.2185 +               *(dp--) = *sp;
  1.2186 +               *(dp--) = *(sp--);
  1.2187 +            }
  1.2188 +         }
  1.2189 +         else
  1.2190 +         {
  1.2191 +            png_bytep sp = row + (png_size_t)row_width * 4 - 1;
  1.2192 +            png_bytep dp = sp  + (png_size_t)row_width * 4;
  1.2193 +            for (i = 0; i < row_width; i++)
  1.2194 +            {
  1.2195 +               *(dp--) = *(sp--);
  1.2196 +               *(dp--) = *(sp--);
  1.2197 +               *(dp--) = *sp;
  1.2198 +               *(dp--) = *(sp - 1);
  1.2199 +               *(dp--) = *sp;
  1.2200 +               *(dp--) = *(sp - 1);
  1.2201 +               *(dp--) = *(sp--);
  1.2202 +               *(dp--) = *(sp--);
  1.2203 +            }
  1.2204 +         }
  1.2205 +      }
  1.2206 +      row_info->channels += (png_byte)2;
  1.2207 +      row_info->color_type |= PNG_COLOR_MASK_COLOR;
  1.2208 +      row_info->pixel_depth = (png_byte)(row_info->channels *
  1.2209 +         row_info->bit_depth);
  1.2210 +      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
  1.2211 +   }
  1.2212 +}
  1.2213 +#endif
  1.2214 +
  1.2215 +#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
  1.2216 +/* reduce RGB files to grayscale, with or without alpha
  1.2217 + * using the equation given in Poynton's ColorFAQ at
  1.2218 + * <http://www.inforamp.net/~poynton/>  (THIS LINK IS DEAD June 2008)
  1.2219 + * New link:
  1.2220 + * <http://www.poynton.com/notes/colour_and_gamma/>
  1.2221 + * Charles Poynton poynton at poynton.com
  1.2222 + *
  1.2223 + *     Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
  1.2224 + *
  1.2225 + *  We approximate this with
  1.2226 + *
  1.2227 + *     Y = 0.21268 * R    + 0.7151 * G    + 0.07217 * B
  1.2228 + *
  1.2229 + *  which can be expressed with integers as
  1.2230 + *
  1.2231 + *     Y = (6969 * R + 23434 * G + 2365 * B)/32768
  1.2232 + *
  1.2233 + *  The calculation is to be done in a linear colorspace.
  1.2234 + *
  1.2235 + *  Other integer coefficents can be used via png_set_rgb_to_gray().
  1.2236 + */
  1.2237 +int /* PRIVATE */
  1.2238 +png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
  1.2239 +
  1.2240 +{
  1.2241 +   png_uint_32 i;
  1.2242 +
  1.2243 +   png_uint_32 row_width = row_info->width;
  1.2244 +   int rgb_error = 0;
  1.2245 +
  1.2246 +   png_debug(1, "in png_do_rgb_to_gray\n");
  1.2247 +   if (
  1.2248 +#if defined(PNG_USELESS_TESTS_SUPPORTED)
  1.2249 +       row != NULL && row_info != NULL &&
  1.2250 +#endif
  1.2251 +      (row_info->color_type & PNG_COLOR_MASK_COLOR))
  1.2252 +   {
  1.2253 +      png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff;
  1.2254 +      png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff;
  1.2255 +      png_uint_32 bc = png_ptr->rgb_to_gray_blue_coeff;
  1.2256 +
  1.2257 +      if (row_info->color_type == PNG_COLOR_TYPE_RGB)
  1.2258 +      {
  1.2259 +         if (row_info->bit_depth == 8)
  1.2260 +         {
  1.2261 +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
  1.2262 +            if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
  1.2263 +            {
  1.2264 +               png_bytep sp = row;
  1.2265 +               png_bytep dp = row;
  1.2266 +
  1.2267 +               for (i = 0; i < row_width; i++)
  1.2268 +               {
  1.2269 +                  png_byte red   = png_ptr->gamma_to_1[*(sp++)];
  1.2270 +                  png_byte green = png_ptr->gamma_to_1[*(sp++)];
  1.2271 +                  png_byte blue  = png_ptr->gamma_to_1[*(sp++)];
  1.2272 +                  if (red != green || red != blue)
  1.2273 +                  {
  1.2274 +                     rgb_error |= 1;
  1.2275 +                     *(dp++) = png_ptr->gamma_from_1[
  1.2276 +                       (rc*red + gc*green + bc*blue)>>15];
  1.2277 +                  }
  1.2278 +                  else
  1.2279 +                     *(dp++) = *(sp - 1);
  1.2280 +               }
  1.2281 +            }
  1.2282 +            else
  1.2283 +#endif
  1.2284 +            {
  1.2285 +               png_bytep sp = row;
  1.2286 +               png_bytep dp = row;
  1.2287 +               for (i = 0; i < row_width; i++)
  1.2288 +               {
  1.2289 +                  png_byte red   = *(sp++);
  1.2290 +                  png_byte green = *(sp++);
  1.2291 +                  png_byte blue  = *(sp++);
  1.2292 +                  if (red != green || red != blue)
  1.2293 +                  {
  1.2294 +                     rgb_error |= 1;
  1.2295 +                     *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15);
  1.2296 +                  }
  1.2297 +                  else
  1.2298 +                     *(dp++) = *(sp - 1);
  1.2299 +               }
  1.2300 +            }
  1.2301 +         }
  1.2302 +
  1.2303 +         else /* RGB bit_depth == 16 */
  1.2304 +         {
  1.2305 +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
  1.2306 +            if (png_ptr->gamma_16_to_1 != NULL &&
  1.2307 +                png_ptr->gamma_16_from_1 != NULL)
  1.2308 +            {
  1.2309 +               png_bytep sp = row;
  1.2310 +               png_bytep dp = row;
  1.2311 +               for (i = 0; i < row_width; i++)
  1.2312 +               {
  1.2313 +                  png_uint_16 red, green, blue, w;
  1.2314 +
  1.2315 +                  red   = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
  1.2316 +                  green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
  1.2317 +                  blue  = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
  1.2318 +
  1.2319 +                  if (red == green && red == blue)
  1.2320 +                     w = red;
  1.2321 +                  else
  1.2322 +                  {
  1.2323 +                     png_uint_16 red_1   = png_ptr->gamma_16_to_1[(red&0xff) >>
  1.2324 +                                  png_ptr->gamma_shift][red>>8];
  1.2325 +                     png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >>
  1.2326 +                                  png_ptr->gamma_shift][green>>8];
  1.2327 +                     png_uint_16 blue_1  = png_ptr->gamma_16_to_1[(blue&0xff) >>
  1.2328 +                                  png_ptr->gamma_shift][blue>>8];
  1.2329 +                     png_uint_16 gray16  = (png_uint_16)((rc*red_1 + gc*green_1
  1.2330 +                                  + bc*blue_1)>>15);
  1.2331 +                     w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
  1.2332 +                         png_ptr->gamma_shift][gray16 >> 8];
  1.2333 +                     rgb_error |= 1;
  1.2334 +                  }
  1.2335 +
  1.2336 +                  *(dp++) = (png_byte)((w>>8) & 0xff);
  1.2337 +                  *(dp++) = (png_byte)(w & 0xff);
  1.2338 +               }
  1.2339 +            }
  1.2340 +            else
  1.2341 +#endif
  1.2342 +            {
  1.2343 +               png_bytep sp = row;
  1.2344 +               png_bytep dp = row;
  1.2345 +               for (i = 0; i < row_width; i++)
  1.2346 +               {
  1.2347 +                  png_uint_16 red, green, blue, gray16;
  1.2348 +
  1.2349 +                  red   = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
  1.2350 +                  green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
  1.2351 +                  blue  = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
  1.2352 +
  1.2353 +                  if (red != green || red != blue)
  1.2354 +                     rgb_error |= 1;
  1.2355 +                  gray16  = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
  1.2356 +                  *(dp++) = (png_byte)((gray16>>8) & 0xff);
  1.2357 +                  *(dp++) = (png_byte)(gray16 & 0xff);
  1.2358 +               }
  1.2359 +            }
  1.2360 +         }
  1.2361 +      }
  1.2362 +      if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
  1.2363 +      {
  1.2364 +         if (row_info->bit_depth == 8)
  1.2365 +         {
  1.2366 +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
  1.2367 +            if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
  1.2368 +            {
  1.2369 +               png_bytep sp = row;
  1.2370 +               png_bytep dp = row;
  1.2371 +               for (i = 0; i < row_width; i++)
  1.2372 +               {
  1.2373 +                  png_byte red   = png_ptr->gamma_to_1[*(sp++)];
  1.2374 +                  png_byte green = png_ptr->gamma_to_1[*(sp++)];
  1.2375 +                  png_byte blue  = png_ptr->gamma_to_1[*(sp++)];
  1.2376 +                  if (red != green || red != blue)
  1.2377 +                     rgb_error |= 1;
  1.2378 +                  *(dp++) =  png_ptr->gamma_from_1
  1.2379 +                             [(rc*red + gc*green + bc*blue)>>15];
  1.2380 +                  *(dp++) = *(sp++);  /* alpha */
  1.2381 +               }
  1.2382 +            }
  1.2383 +            else
  1.2384 +#endif
  1.2385 +            {
  1.2386 +               png_bytep sp = row;
  1.2387 +               png_bytep dp = row;
  1.2388 +               for (i = 0; i < row_width; i++)
  1.2389 +               {
  1.2390 +                  png_byte red   = *(sp++);
  1.2391 +                  png_byte green = *(sp++);
  1.2392 +                  png_byte blue  = *(sp++);
  1.2393 +                  if (red != green || red != blue)
  1.2394 +                     rgb_error |= 1;
  1.2395 +                  *(dp++) =  (png_byte)((rc*red + gc*green + bc*blue)>>15);
  1.2396 +                  *(dp++) = *(sp++);  /* alpha */
  1.2397 +               }
  1.2398 +            }
  1.2399 +         }
  1.2400 +         else /* RGBA bit_depth == 16 */
  1.2401 +         {
  1.2402 +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
  1.2403 +            if (png_ptr->gamma_16_to_1 != NULL &&
  1.2404 +                png_ptr->gamma_16_from_1 != NULL)
  1.2405 +            {
  1.2406 +               png_bytep sp = row;
  1.2407 +               png_bytep dp = row;
  1.2408 +               for (i = 0; i < row_width; i++)
  1.2409 +               {
  1.2410 +                  png_uint_16 red, green, blue, w;
  1.2411 +
  1.2412 +                  red   = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
  1.2413 +                  green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
  1.2414 +                  blue  = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
  1.2415 +
  1.2416 +                  if (red == green && red == blue)
  1.2417 +                     w = red;
  1.2418 +                  else
  1.2419 +                  {
  1.2420 +                     png_uint_16 red_1   = png_ptr->gamma_16_to_1[(red&0xff) >>
  1.2421 +                                  png_ptr->gamma_shift][red>>8];
  1.2422 +                     png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >>
  1.2423 +                                  png_ptr->gamma_shift][green>>8];
  1.2424 +                     png_uint_16 blue_1  = png_ptr->gamma_16_to_1[(blue&0xff) >>
  1.2425 +                                  png_ptr->gamma_shift][blue>>8];
  1.2426 +                     png_uint_16 gray16  = (png_uint_16)((rc * red_1
  1.2427 +                                  + gc * green_1 + bc * blue_1)>>15);
  1.2428 +                     w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
  1.2429 +                         png_ptr->gamma_shift][gray16 >> 8];
  1.2430 +                     rgb_error |= 1;
  1.2431 +                  }
  1.2432 +
  1.2433 +                  *(dp++) = (png_byte)((w>>8) & 0xff);
  1.2434 +                  *(dp++) = (png_byte)(w & 0xff);
  1.2435 +                  *(dp++) = *(sp++);  /* alpha */
  1.2436 +                  *(dp++) = *(sp++);
  1.2437 +               }
  1.2438 +            }
  1.2439 +            else
  1.2440 +#endif
  1.2441 +            {
  1.2442 +               png_bytep sp = row;
  1.2443 +               png_bytep dp = row;
  1.2444 +               for (i = 0; i < row_width; i++)
  1.2445 +               {
  1.2446 +                  png_uint_16 red, green, blue, gray16;
  1.2447 +                  red   = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
  1.2448 +                  green = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
  1.2449 +                  blue  = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
  1.2450 +                  if (red != green || red != blue)
  1.2451 +                     rgb_error |= 1;
  1.2452 +                  gray16  = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
  1.2453 +                  *(dp++) = (png_byte)((gray16>>8) & 0xff);
  1.2454 +                  *(dp++) = (png_byte)(gray16 & 0xff);
  1.2455 +                  *(dp++) = *(sp++);  /* alpha */
  1.2456 +                  *(dp++) = *(sp++);
  1.2457 +               }
  1.2458 +            }
  1.2459 +         }
  1.2460 +      }
  1.2461 +   row_info->channels -= (png_byte)2;
  1.2462 +      row_info->color_type &= ~PNG_COLOR_MASK_COLOR;
  1.2463 +      row_info->pixel_depth = (png_byte)(row_info->channels *
  1.2464 +         row_info->bit_depth);
  1.2465 +      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
  1.2466 +   }
  1.2467 +   return rgb_error;
  1.2468 +}
  1.2469 +#endif
  1.2470 +
  1.2471 +/* Build a grayscale palette.  Palette is assumed to be 1 << bit_depth
  1.2472 + * large of png_color.  This lets grayscale images be treated as
  1.2473 + * paletted.  Most useful for gamma correction and simplification
  1.2474 + * of code.
  1.2475 + */
  1.2476 +void PNGAPI
  1.2477 +png_build_grayscale_palette(int bit_depth, png_colorp palette)
  1.2478 +{
  1.2479 +   int num_palette;
  1.2480 +   int color_inc;
  1.2481 +   int i;
  1.2482 +   int v;
  1.2483 +
  1.2484 +   png_debug(1, "in png_do_build_grayscale_palette\n");
  1.2485 +   if (palette == NULL)
  1.2486 +      return;
  1.2487 +
  1.2488 +   switch (bit_depth)
  1.2489 +   {
  1.2490 +      case 1:
  1.2491 +         num_palette = 2;
  1.2492 +         color_inc = 0xff;
  1.2493 +         break;
  1.2494 +      case 2:
  1.2495 +         num_palette = 4;
  1.2496 +         color_inc = 0x55;
  1.2497 +         break;
  1.2498 +      case 4:
  1.2499 +         num_palette = 16;
  1.2500 +         color_inc = 0x11;
  1.2501 +         break;
  1.2502 +      case 8:
  1.2503 +         num_palette = 256;
  1.2504 +         color_inc = 1;
  1.2505 +         break;
  1.2506 +      default:
  1.2507 +         num_palette = 0;
  1.2508 +         color_inc = 0;
  1.2509 +         break;
  1.2510 +   }
  1.2511 +
  1.2512 +   for (i = 0, v = 0; i < num_palette; i++, v += color_inc)
  1.2513 +   {
  1.2514 +      palette[i].red = (png_byte)v;
  1.2515 +      palette[i].green = (png_byte)v;
  1.2516 +      palette[i].blue = (png_byte)v;
  1.2517 +   }
  1.2518 +}
  1.2519 +
  1.2520 +/* This function is currently unused.  Do we really need it? */
  1.2521 +#if defined(PNG_READ_DITHER_SUPPORTED) && defined(PNG_CORRECT_PALETTE_SUPPORTED)
  1.2522 +void /* PRIVATE */
  1.2523 +png_correct_palette(png_structp png_ptr, png_colorp palette,
  1.2524 +   int num_palette)
  1.2525 +{
  1.2526 +   png_debug(1, "in png_correct_palette\n");
  1.2527 +#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
  1.2528 +    defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
  1.2529 +   if (png_ptr->transformations & (PNG_GAMMA | PNG_BACKGROUND))
  1.2530 +   {
  1.2531 +      png_color back, back_1;
  1.2532 +
  1.2533 +      if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
  1.2534 +      {
  1.2535 +         back.red = png_ptr->gamma_table[png_ptr->background.red];
  1.2536 +         back.green = png_ptr->gamma_table[png_ptr->background.green];
  1.2537 +         back.blue = png_ptr->gamma_table[png_ptr->background.blue];
  1.2538 +
  1.2539 +         back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
  1.2540 +         back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
  1.2541 +         back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
  1.2542 +      }
  1.2543 +      else
  1.2544 +      {
  1.2545 +         double g;
  1.2546 +
  1.2547 +         g = 1.0 / (png_ptr->background_gamma * png_ptr->screen_gamma);
  1.2548 +
  1.2549 +         if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_SCREEN ||
  1.2550 +             fabs(g - 1.0) < PNG_GAMMA_THRESHOLD)
  1.2551 +         {
  1.2552 +            back.red = png_ptr->background.red;
  1.2553 +            back.green = png_ptr->background.green;
  1.2554 +            back.blue = png_ptr->background.blue;
  1.2555 +         }
  1.2556 +         else
  1.2557 +         {
  1.2558 +            back.red =
  1.2559 +               (png_byte)(pow((double)png_ptr->background.red/255, g) *
  1.2560 +                255.0 + 0.5);
  1.2561 +            back.green =
  1.2562 +               (png_byte)(pow((double)png_ptr->background.green/255, g) *
  1.2563 +                255.0 + 0.5);
  1.2564 +            back.blue =
  1.2565 +               (png_byte)(pow((double)png_ptr->background.blue/255, g) *
  1.2566 +                255.0 + 0.5);
  1.2567 +         }
  1.2568 +
  1.2569 +         g = 1.0 / png_ptr->background_gamma;
  1.2570 +
  1.2571 +         back_1.red =
  1.2572 +            (png_byte)(pow((double)png_ptr->background.red/255, g) *
  1.2573 +             255.0 + 0.5);
  1.2574 +         back_1.green =
  1.2575 +            (png_byte)(pow((double)png_ptr->background.green/255, g) *
  1.2576 +             255.0 + 0.5);
  1.2577 +         back_1.blue =
  1.2578 +            (png_byte)(pow((double)png_ptr->background.blue/255, g) *
  1.2579 +             255.0 + 0.5);
  1.2580 +      }
  1.2581 +
  1.2582 +      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
  1.2583 +      {
  1.2584 +         png_uint_32 i;
  1.2585 +
  1.2586 +         for (i = 0; i < (png_uint_32)num_palette; i++)
  1.2587 +         {
  1.2588 +            if (i < png_ptr->num_trans && png_ptr->trans[i] == 0)
  1.2589 +            {
  1.2590 +               palette[i] = back;
  1.2591 +            }
  1.2592 +            else if (i < png_ptr->num_trans && png_ptr->trans[i] != 0xff)
  1.2593 +            {
  1.2594 +               png_byte v, w;
  1.2595 +
  1.2596 +               v = png_ptr->gamma_to_1[png_ptr->palette[i].red];
  1.2597 +               png_composite(w, v, png_ptr->trans[i], back_1.red);
  1.2598 +               palette[i].red = png_ptr->gamma_from_1[w];
  1.2599 +
  1.2600 +               v = png_ptr->gamma_to_1[png_ptr->palette[i].green];
  1.2601 +               png_composite(w, v, png_ptr->trans[i], back_1.green);
  1.2602 +               palette[i].green = png_ptr->gamma_from_1[w];
  1.2603 +
  1.2604 +               v = png_ptr->gamma_to_1[png_ptr->palette[i].blue];
  1.2605 +               png_composite(w, v, png_ptr->trans[i], back_1.blue);
  1.2606 +               palette[i].blue = png_ptr->gamma_from_1[w];
  1.2607 +            }
  1.2608 +            else
  1.2609 +            {
  1.2610 +               palette[i].red = png_ptr->gamma_table[palette[i].red];
  1.2611 +               palette[i].green = png_ptr->gamma_table[palette[i].green];
  1.2612 +               palette[i].blue = png_ptr->gamma_table[palette[i].blue];
  1.2613 +            }
  1.2614 +         }
  1.2615 +      }
  1.2616 +      else
  1.2617 +      {
  1.2618 +         int i;
  1.2619 +
  1.2620 +         for (i = 0; i < num_palette; i++)
  1.2621 +         {
  1.2622 +            if (palette[i].red == (png_byte)png_ptr->trans_values.gray)
  1.2623 +            {
  1.2624 +               palette[i] = back;
  1.2625 +            }
  1.2626 +            else
  1.2627 +            {
  1.2628 +               palette[i].red = png_ptr->gamma_table[palette[i].red];
  1.2629 +               palette[i].green = png_ptr->gamma_table[palette[i].green];
  1.2630 +               palette[i].blue = png_ptr->gamma_table[palette[i].blue];
  1.2631 +            }
  1.2632 +         }
  1.2633 +      }
  1.2634 +   }
  1.2635 +   else
  1.2636 +#endif
  1.2637 +#if defined(PNG_READ_GAMMA_SUPPORTED)
  1.2638 +   if (png_ptr->transformations & PNG_GAMMA)
  1.2639 +   {
  1.2640 +      int i;
  1.2641 +
  1.2642 +      for (i = 0; i < num_palette; i++)
  1.2643 +      {
  1.2644 +         palette[i].red = png_ptr->gamma_table[palette[i].red];
  1.2645 +         palette[i].green = png_ptr->gamma_table[palette[i].green];
  1.2646 +         palette[i].blue = png_ptr->gamma_table[palette[i].blue];
  1.2647 +      }
  1.2648 +   }
  1.2649 +#if defined(PNG_READ_BACKGROUND_SUPPORTED)
  1.2650 +   else
  1.2651 +#endif
  1.2652 +#endif
  1.2653 +#if defined(PNG_READ_BACKGROUND_SUPPORTED)
  1.2654 +   if (png_ptr->transformations & PNG_BACKGROUND)
  1.2655 +   {
  1.2656 +      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
  1.2657 +      {
  1.2658 +         png_color back;
  1.2659 +
  1.2660 +         back.red   = (png_byte)png_ptr->background.red;
  1.2661 +         back.green = (png_byte)png_ptr->background.green;
  1.2662 +         back.blue  = (png_byte)png_ptr->background.blue;
  1.2663 +
  1.2664 +         for (i = 0; i < (int)png_ptr->num_trans; i++)
  1.2665 +         {
  1.2666 +            if (png_ptr->trans[i] == 0)
  1.2667 +            {
  1.2668 +               palette[i].red = back.red;
  1.2669 +               palette[i].green = back.green;
  1.2670 +               palette[i].blue = back.blue;
  1.2671 +            }
  1.2672 +            else if (png_ptr->trans[i] != 0xff)
  1.2673 +            {
  1.2674 +               png_composite(palette[i].red, png_ptr->palette[i].red,
  1.2675 +                  png_ptr->trans[i], back.red);
  1.2676 +               png_composite(palette[i].green, png_ptr->palette[i].green,
  1.2677 +                  png_ptr->trans[i], back.green);
  1.2678 +               png_composite(palette[i].blue, png_ptr->palette[i].blue,
  1.2679 +                  png_ptr->trans[i], back.blue);
  1.2680 +            }
  1.2681 +         }
  1.2682 +      }
  1.2683 +      else /* assume grayscale palette (what else could it be?) */
  1.2684 +      {
  1.2685 +         int i;
  1.2686 +
  1.2687 +         for (i = 0; i < num_palette; i++)
  1.2688 +         {
  1.2689 +            if (i == (png_byte)png_ptr->trans_values.gray)
  1.2690 +            {
  1.2691 +               palette[i].red = (png_byte)png_ptr->background.red;
  1.2692 +               palette[i].green = (png_byte)png_ptr->background.green;
  1.2693 +               palette[i].blue = (png_byte)png_ptr->background.blue;
  1.2694 +            }
  1.2695 +         }
  1.2696 +      }
  1.2697 +   }
  1.2698 +#endif
  1.2699 +}
  1.2700 +#endif
  1.2701 +
  1.2702 +#if defined(PNG_READ_BACKGROUND_SUPPORTED)
  1.2703 +/* Replace any alpha or transparency with the supplied background color.
  1.2704 + * "background" is already in the screen gamma, while "background_1" is
  1.2705 + * at a gamma of 1.0.  Paletted files have already been taken care of.
  1.2706 + */
  1.2707 +void /* PRIVATE */
  1.2708 +png_do_background(png_row_infop row_info, png_bytep row,
  1.2709 +   png_color_16p trans_values, png_color_16p background
  1.2710 +#if defined(PNG_READ_GAMMA_SUPPORTED)
  1.2711 +   , png_color_16p background_1,
  1.2712 +   png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1,
  1.2713 +   png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1,
  1.2714 +   png_uint_16pp gamma_16_to_1, int gamma_shift
  1.2715 +#endif
  1.2716 +   )
  1.2717 +{
  1.2718 +   png_bytep sp, dp;
  1.2719 +   png_uint_32 i;
  1.2720 +   png_uint_32 row_width=row_info->width;
  1.2721 +   int shift;
  1.2722 +
  1.2723 +   png_debug(1, "in png_do_background\n");
  1.2724 +   if (background != NULL &&
  1.2725 +#if defined(PNG_USELESS_TESTS_SUPPORTED)
  1.2726 +       row != NULL && row_info != NULL &&
  1.2727 +#endif
  1.2728 +      (!(row_info->color_type & PNG_COLOR_MASK_ALPHA) ||
  1.2729 +      (row_info->color_type != PNG_COLOR_TYPE_PALETTE && trans_values)))
  1.2730 +   {
  1.2731 +      switch (row_info->color_type)
  1.2732 +      {
  1.2733 +         case PNG_COLOR_TYPE_GRAY:
  1.2734 +         {
  1.2735 +            switch (row_info->bit_depth)
  1.2736 +            {
  1.2737 +               case 1:
  1.2738 +               {
  1.2739 +                  sp = row;
  1.2740 +                  shift = 7;
  1.2741 +                  for (i = 0; i < row_width; i++)
  1.2742 +                  {
  1.2743 +                     if ((png_uint_16)((*sp >> shift) & 0x01)
  1.2744 +                        == trans_values->gray)
  1.2745 +                     {
  1.2746 +                        *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
  1.2747 +                        *sp |= (png_byte)(background->gray << shift);
  1.2748 +                     }
  1.2749 +                     if (!shift)
  1.2750 +                     {
  1.2751 +                        shift = 7;
  1.2752 +                        sp++;
  1.2753 +                     }
  1.2754 +                     else
  1.2755 +                        shift--;
  1.2756 +                  }
  1.2757 +                  break;
  1.2758 +               }
  1.2759 +               case 2:
  1.2760 +               {
  1.2761 +#if defined(PNG_READ_GAMMA_SUPPORTED)
  1.2762 +                  if (gamma_table != NULL)
  1.2763 +                  {
  1.2764 +                     sp = row;
  1.2765 +                     shift = 6;
  1.2766 +                     for (i = 0; i < row_width; i++)
  1.2767 +                     {
  1.2768 +                        if ((png_uint_16)((*sp >> shift) & 0x03)
  1.2769 +                            == trans_values->gray)
  1.2770 +                        {
  1.2771 +                           *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
  1.2772 +                           *sp |= (png_byte)(background->gray << shift);
  1.2773 +                        }
  1.2774 +                        else
  1.2775 +                        {
  1.2776 +                           png_byte p = (png_byte)((*sp >> shift) & 0x03);
  1.2777 +                           png_byte g = (png_byte)((gamma_table [p | (p << 2) |
  1.2778 +                               (p << 4) | (p << 6)] >> 6) & 0x03);
  1.2779 +                           *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
  1.2780 +                           *sp |= (png_byte)(g << shift);
  1.2781 +                        }
  1.2782 +                        if (!shift)
  1.2783 +                        {
  1.2784 +                           shift = 6;
  1.2785 +                           sp++;
  1.2786 +                        }
  1.2787 +                        else
  1.2788 +                           shift -= 2;
  1.2789 +                     }
  1.2790 +                  }
  1.2791 +                  else
  1.2792 +#endif
  1.2793 +                  {
  1.2794 +                     sp = row;
  1.2795 +                     shift = 6;
  1.2796 +                     for (i = 0; i < row_width; i++)
  1.2797 +                     {
  1.2798 +                        if ((png_uint_16)((*sp >> shift) & 0x03)
  1.2799 +                            == trans_values->gray)
  1.2800 +                        {
  1.2801 +                           *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
  1.2802 +                           *sp |= (png_byte)(background->gray << shift);
  1.2803 +                        }
  1.2804 +                        if (!shift)
  1.2805 +                        {
  1.2806 +                           shift = 6;
  1.2807 +                           sp++;
  1.2808 +                        }
  1.2809 +                        else
  1.2810 +                           shift -= 2;
  1.2811 +                     }
  1.2812 +                  }
  1.2813 +                  break;
  1.2814 +               }
  1.2815 +               case 4:
  1.2816 +               {
  1.2817 +#if defined(PNG_READ_GAMMA_SUPPORTED)
  1.2818 +                  if (gamma_table != NULL)
  1.2819 +                  {
  1.2820 +                     sp = row;
  1.2821 +                     shift = 4;
  1.2822 +                     for (i = 0; i < row_width; i++)
  1.2823 +                     {
  1.2824 +                        if ((png_uint_16)((*sp >> shift) & 0x0f)
  1.2825 +                            == trans_values->gray)
  1.2826 +                        {
  1.2827 +                           *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
  1.2828 +                           *sp |= (png_byte)(background->gray << shift);
  1.2829 +                        }
  1.2830 +                        else
  1.2831 +                        {
  1.2832 +                           png_byte p = (png_byte)((*sp >> shift) & 0x0f);
  1.2833 +                           png_byte g = (png_byte)((gamma_table[p |
  1.2834 +                             (p << 4)] >> 4) & 0x0f);
  1.2835 +                           *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
  1.2836 +                           *sp |= (png_byte)(g << shift);
  1.2837 +                        }
  1.2838 +                        if (!shift)
  1.2839 +                        {
  1.2840 +                           shift = 4;
  1.2841 +                           sp++;
  1.2842 +                        }
  1.2843 +                        else
  1.2844 +                           shift -= 4;
  1.2845 +                     }
  1.2846 +                  }
  1.2847 +                  else
  1.2848 +#endif
  1.2849 +                  {
  1.2850 +                     sp = row;
  1.2851 +                     shift = 4;
  1.2852 +                     for (i = 0; i < row_width; i++)
  1.2853 +                     {
  1.2854 +                        if ((png_uint_16)((*sp >> shift) & 0x0f)
  1.2855 +                            == trans_values->gray)
  1.2856 +                        {
  1.2857 +                           *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
  1.2858 +                           *sp |= (png_byte)(background->gray << shift);
  1.2859 +                        }
  1.2860 +                        if (!shift)
  1.2861 +                        {
  1.2862 +                           shift = 4;
  1.2863 +                           sp++;
  1.2864 +                        }
  1.2865 +                        else
  1.2866 +                           shift -= 4;
  1.2867 +                     }
  1.2868 +                  }
  1.2869 +                  break;
  1.2870 +               }
  1.2871 +               case 8:
  1.2872 +               {
  1.2873 +#if defined(PNG_READ_GAMMA_SUPPORTED)
  1.2874 +                  if (gamma_table != NULL)
  1.2875 +                  {
  1.2876 +                     sp = row;
  1.2877 +                     for (i = 0; i < row_width; i++, sp++)
  1.2878 +                     {
  1.2879 +                        if (*sp == trans_values->gray)
  1.2880 +                        {
  1.2881 +                           *sp = (png_byte)background->gray;
  1.2882 +                        }
  1.2883 +                        else
  1.2884 +                        {
  1.2885 +                           *sp = gamma_table[*sp];
  1.2886 +                        }
  1.2887 +                     }
  1.2888 +                  }
  1.2889 +                  else
  1.2890 +#endif
  1.2891 +                  {
  1.2892 +                     sp = row;
  1.2893 +                     for (i = 0; i < row_width; i++, sp++)
  1.2894 +                     {
  1.2895 +                        if (*sp == trans_values->gray)
  1.2896 +                        {
  1.2897 +                           *sp = (png_byte)background->gray;
  1.2898 +                        }
  1.2899 +                     }
  1.2900 +                  }
  1.2901 +                  break;
  1.2902 +               }
  1.2903 +               case 16:
  1.2904 +               {
  1.2905 +#if defined(PNG_READ_GAMMA_SUPPORTED)
  1.2906 +                  if (gamma_16 != NULL)
  1.2907 +                  {
  1.2908 +                     sp = row;
  1.2909 +                     for (i = 0; i < row_width; i++, sp += 2)
  1.2910 +                     {
  1.2911 +                        png_uint_16 v;
  1.2912 +
  1.2913 +                        v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
  1.2914 +                        if (v == trans_values->gray)
  1.2915 +                        {
  1.2916 +                           /* background is already in screen gamma */
  1.2917 +                           *sp = (png_byte)((background->gray >> 8) & 0xff);
  1.2918 +                           *(sp + 1) = (png_byte)(background->gray & 0xff);
  1.2919 +                        }
  1.2920 +                        else
  1.2921 +                        {
  1.2922 +                           v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
  1.2923 +                           *sp = (png_byte)((v >> 8) & 0xff);
  1.2924 +                           *(sp + 1) = (png_byte)(v & 0xff);
  1.2925 +                        }
  1.2926 +                     }
  1.2927 +                  }
  1.2928 +                  else
  1.2929 +#endif
  1.2930 +                  {
  1.2931 +                     sp = row;
  1.2932 +                     for (i = 0; i < row_width; i++, sp += 2)
  1.2933 +                     {
  1.2934 +                        png_uint_16 v;
  1.2935 +
  1.2936 +                        v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
  1.2937 +                        if (v == trans_values->gray)
  1.2938 +                        {
  1.2939 +                           *sp = (png_byte)((background->gray >> 8) & 0xff);
  1.2940 +                           *(sp + 1) = (png_byte)(background->gray & 0xff);
  1.2941 +                        }
  1.2942 +                     }
  1.2943 +                  }
  1.2944 +                  break;
  1.2945 +               }
  1.2946 +            }
  1.2947 +            break;
  1.2948 +         }
  1.2949 +         case PNG_COLOR_TYPE_RGB:
  1.2950 +         {
  1.2951 +            if (row_info->bit_depth == 8)
  1.2952 +            {
  1.2953 +#if defined(PNG_READ_GAMMA_SUPPORTED)
  1.2954 +               if (gamma_table != NULL)
  1.2955 +               {
  1.2956 +                  sp = row;
  1.2957 +                  for (i = 0; i < row_width; i++, sp += 3)
  1.2958 +                  {
  1.2959 +                     if (*sp == trans_values->red &&
  1.2960 +                        *(sp + 1) == trans_values->green &&
  1.2961 +                        *(sp + 2) == trans_values->blue)
  1.2962 +                     {
  1.2963 +                        *sp = (png_byte)background->red;
  1.2964 +                        *(sp + 1) = (png_byte)background->green;
  1.2965 +                        *(sp + 2) = (png_byte)background->blue;
  1.2966 +                     }
  1.2967 +                     else
  1.2968 +                     {
  1.2969 +                        *sp = gamma_table[*sp];
  1.2970 +                        *(sp + 1) = gamma_table[*(sp + 1)];
  1.2971 +                        *(sp + 2) = gamma_table[*(sp + 2)];
  1.2972 +                     }
  1.2973 +                  }
  1.2974 +               }
  1.2975 +               else
  1.2976 +#endif
  1.2977 +               {
  1.2978 +                  sp = row;
  1.2979 +                  for (i = 0; i < row_width; i++, sp += 3)
  1.2980 +                  {
  1.2981 +                     if (*sp == trans_values->red &&
  1.2982 +                        *(sp + 1) == trans_values->green &&
  1.2983 +                        *(sp + 2) == trans_values->blue)
  1.2984 +                     {
  1.2985 +                        *sp = (png_byte)background->red;
  1.2986 +                        *(sp + 1) = (png_byte)background->green;
  1.2987 +                        *(sp + 2) = (png_byte)background->blue;
  1.2988 +                     }
  1.2989 +                  }
  1.2990 +               }
  1.2991 +            }
  1.2992 +            else /* if (row_info->bit_depth == 16) */
  1.2993 +            {
  1.2994 +#if defined(PNG_READ_GAMMA_SUPPORTED)
  1.2995 +               if (gamma_16 != NULL)
  1.2996 +               {
  1.2997 +                  sp = row;
  1.2998 +                  for (i = 0; i < row_width; i++, sp += 6)
  1.2999 +                  {
  1.3000 +                     png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
  1.3001 +                     png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
  1.3002 +                     png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5));
  1.3003 +                     if (r == trans_values->red && g == trans_values->green &&
  1.3004 +                        b == trans_values->blue)
  1.3005 +                     {
  1.3006 +                        /* background is already in screen gamma */
  1.3007 +                        *sp = (png_byte)((background->red >> 8) & 0xff);
  1.3008 +                        *(sp + 1) = (png_byte)(background->red & 0xff);
  1.3009 +                        *(sp + 2) = (png_byte)((background->green >> 8) & 0xff);
  1.3010 +                        *(sp + 3) = (png_byte)(background->green & 0xff);
  1.3011 +                        *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff);
  1.3012 +                        *(sp + 5) = (png_byte)(background->blue & 0xff);
  1.3013 +                     }
  1.3014 +                     else
  1.3015 +                     {
  1.3016 +                        png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
  1.3017 +                        *sp = (png_byte)((v >> 8) & 0xff);
  1.3018 +                        *(sp + 1) = (png_byte)(v & 0xff);
  1.3019 +                        v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
  1.3020 +                        *(sp + 2) = (png_byte)((v >> 8) & 0xff);
  1.3021 +                        *(sp + 3) = (png_byte)(v & 0xff);
  1.3022 +                        v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
  1.3023 +                        *(sp + 4) = (png_byte)((v >> 8) & 0xff);
  1.3024 +                        *(sp + 5) = (png_byte)(v & 0xff);
  1.3025 +                     }
  1.3026 +                  }
  1.3027 +               }
  1.3028 +               else
  1.3029 +#endif
  1.3030 +               {
  1.3031 +                  sp = row;
  1.3032 +                  for (i = 0; i < row_width; i++, sp += 6)
  1.3033 +                  {
  1.3034 +                     png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp+1));
  1.3035 +                     png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
  1.3036 +                     png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5));
  1.3037 +
  1.3038 +                     if (r == trans_values->red && g == trans_values->green &&
  1.3039 +                        b == trans_values->blue)
  1.3040 +                     {
  1.3041 +                        *sp = (png_byte)((background->red >> 8) & 0xff);
  1.3042 +                        *(sp + 1) = (png_byte)(background->red & 0xff);
  1.3043 +                        *(sp + 2) = (png_byte)((background->green >> 8) & 0xff);
  1.3044 +                        *(sp + 3) = (png_byte)(background->green & 0xff);
  1.3045 +                        *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff);
  1.3046 +                        *(sp + 5) = (png_byte)(background->blue & 0xff);
  1.3047 +                     }
  1.3048 +                  }
  1.3049 +               }
  1.3050 +            }
  1.3051 +            break;
  1.3052 +         }
  1.3053 +         case PNG_COLOR_TYPE_GRAY_ALPHA:
  1.3054 +         {
  1.3055 +            if (row_info->bit_depth == 8)
  1.3056 +            {
  1.3057 +#if defined(PNG_READ_GAMMA_SUPPORTED)
  1.3058 +               if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
  1.3059 +                   gamma_table != NULL)
  1.3060 +               {
  1.3061 +                  sp = row;
  1.3062 +                  dp = row;
  1.3063 +                  for (i = 0; i < row_width; i++, sp += 2, dp++)
  1.3064 +                  {
  1.3065 +                     png_uint_16 a = *(sp + 1);
  1.3066 +
  1.3067 +                     if (a == 0xff)
  1.3068 +                     {
  1.3069 +                        *dp = gamma_table[*sp];
  1.3070 +                     }
  1.3071 +                     else if (a == 0)
  1.3072 +                     {
  1.3073 +                        /* background is already in screen gamma */
  1.3074 +                        *dp = (png_byte)background->gray;
  1.3075 +                     }
  1.3076 +                     else
  1.3077 +                     {
  1.3078 +                        png_byte v, w;
  1.3079 +
  1.3080 +                        v = gamma_to_1[*sp];
  1.3081 +                        png_composite(w, v, a, background_1->gray);
  1.3082 +                        *dp = gamma_from_1[w];
  1.3083 +                     }
  1.3084 +                  }
  1.3085 +               }
  1.3086 +               else
  1.3087 +#endif
  1.3088 +               {
  1.3089 +                  sp = row;
  1.3090 +                  dp = row;
  1.3091 +                  for (i = 0; i < row_width; i++, sp += 2, dp++)
  1.3092 +                  {
  1.3093 +                     png_byte a = *(sp + 1);
  1.3094 +
  1.3095 +                     if (a == 0xff)
  1.3096 +                     {
  1.3097 +                        *dp = *sp;
  1.3098 +                     }
  1.3099 +#if defined(PNG_READ_GAMMA_SUPPORTED)
  1.3100 +                     else if (a == 0)
  1.3101 +                     {
  1.3102 +                        *dp = (png_byte)background->gray;
  1.3103 +                     }
  1.3104 +                     else
  1.3105 +                     {
  1.3106 +                        png_composite(*dp, *sp, a, background_1->gray);
  1.3107 +                     }
  1.3108 +#else
  1.3109 +                     *dp = (png_byte)background->gray;
  1.3110 +#endif
  1.3111 +                  }
  1.3112 +               }
  1.3113 +            }
  1.3114 +            else /* if (png_ptr->bit_depth == 16) */
  1.3115 +            {
  1.3116 +#if defined(PNG_READ_GAMMA_SUPPORTED)
  1.3117 +               if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
  1.3118 +                   gamma_16_to_1 != NULL)
  1.3119 +               {
  1.3120 +                  sp = row;
  1.3121 +                  dp = row;
  1.3122 +                  for (i = 0; i < row_width; i++, sp += 4, dp += 2)
  1.3123 +                  {
  1.3124 +                     png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
  1.3125 +
  1.3126 +                     if (a == (png_uint_16)0xffff)
  1.3127 +                     {
  1.3128 +                        png_uint_16 v;
  1.3129 +
  1.3130 +                        v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
  1.3131 +                        *dp = (png_byte)((v >> 8) & 0xff);
  1.3132 +                        *(dp + 1) = (png_byte)(v & 0xff);
  1.3133 +                     }
  1.3134 +#if defined(PNG_READ_GAMMA_SUPPORTED)
  1.3135 +                     else if (a == 0)
  1.3136 +#else
  1.3137 +                     else
  1.3138 +#endif
  1.3139 +                     {
  1.3140 +                        /* background is already in screen gamma */
  1.3141 +                        *dp = (png_byte)((background->gray >> 8) & 0xff);
  1.3142 +                        *(dp + 1) = (png_byte)(background->gray & 0xff);
  1.3143 +                     }
  1.3144 +#if defined(PNG_READ_GAMMA_SUPPORTED)
  1.3145 +                     else
  1.3146 +                     {
  1.3147 +                        png_uint_16 g, v, w;
  1.3148 +
  1.3149 +                        g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
  1.3150 +                        png_composite_16(v, g, a, background_1->gray);
  1.3151 +                        w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8];
  1.3152 +                        *dp = (png_byte)((w >> 8) & 0xff);
  1.3153 +                        *(dp + 1) = (png_byte)(w & 0xff);
  1.3154 +                     }
  1.3155 +#endif
  1.3156 +                  }
  1.3157 +               }
  1.3158 +               else
  1.3159 +#endif
  1.3160 +               {
  1.3161 +                  sp = row;
  1.3162 +                  dp = row;
  1.3163 +                  for (i = 0; i < row_width; i++, sp += 4, dp += 2)
  1.3164 +                  {
  1.3165 +                     png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
  1.3166 +                     if (a == (png_uint_16)0xffff)
  1.3167 +                     {
  1.3168 +                        png_memcpy(dp, sp, 2);
  1.3169 +                     }
  1.3170 +#if defined(PNG_READ_GAMMA_SUPPORTED)
  1.3171 +                     else if (a == 0)
  1.3172 +#else
  1.3173 +                     else
  1.3174 +#endif
  1.3175 +                     {
  1.3176 +                        *dp = (png_byte)((background->gray >> 8) & 0xff);
  1.3177 +                        *(dp + 1) = (png_byte)(background->gray & 0xff);
  1.3178 +                     }
  1.3179 +#if defined(PNG_READ_GAMMA_SUPPORTED)
  1.3180 +                     else
  1.3181 +                     {
  1.3182 +                        png_uint_16 g, v;
  1.3183 +
  1.3184 +                        g = (png_uint_16)(((*sp) << 8) + *(sp + 1));
  1.3185 +                        png_composite_16(v, g, a, background_1->gray);
  1.3186 +                        *dp = (png_byte)((v >> 8) & 0xff);
  1.3187 +                        *(dp + 1) = (png_byte)(v & 0xff);
  1.3188 +                     }
  1.3189 +#endif
  1.3190 +                  }
  1.3191 +               }
  1.3192 +            }
  1.3193 +            break;
  1.3194 +         }
  1.3195 +         case PNG_COLOR_TYPE_RGB_ALPHA:
  1.3196 +         {
  1.3197 +            if (row_info->bit_depth == 8)
  1.3198 +            {
  1.3199 +#if defined(PNG_READ_GAMMA_SUPPORTED)
  1.3200 +               if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
  1.3201 +                   gamma_table != NULL)
  1.3202 +               {
  1.3203 +                  sp = row;
  1.3204 +                  dp = row;
  1.3205 +                  for (i = 0; i < row_width; i++, sp += 4, dp += 3)
  1.3206 +                  {
  1.3207 +                     png_byte a = *(sp + 3);
  1.3208 +
  1.3209 +                     if (a == 0xff)
  1.3210 +                     {
  1.3211 +                        *dp = gamma_table[*sp];
  1.3212 +                        *(dp + 1) = gamma_table[*(sp + 1)];
  1.3213 +                        *(dp + 2) = gamma_table[*(sp + 2)];
  1.3214 +                     }
  1.3215 +                     else if (a == 0)
  1.3216 +                     {
  1.3217 +                        /* background is already in screen gamma */
  1.3218 +                        *dp = (png_byte)background->red;
  1.3219 +                        *(dp + 1) = (png_byte)background->green;
  1.3220 +                        *(dp + 2) = (png_byte)background->blue;
  1.3221 +                     }
  1.3222 +                     else
  1.3223 +                     {
  1.3224 +                        png_byte v, w;
  1.3225 +
  1.3226 +                        v = gamma_to_1[*sp];
  1.3227 +                        png_composite(w, v, a, background_1->red);
  1.3228 +                        *dp = gamma_from_1[w];
  1.3229 +                        v = gamma_to_1[*(sp + 1)];
  1.3230 +                        png_composite(w, v, a, background_1->green);
  1.3231 +                        *(dp + 1) = gamma_from_1[w];
  1.3232 +                        v = gamma_to_1[*(sp + 2)];
  1.3233 +                        png_composite(w, v, a, background_1->blue);
  1.3234 +                        *(dp + 2) = gamma_from_1[w];
  1.3235 +                     }
  1.3236 +                  }
  1.3237 +               }
  1.3238 +               else
  1.3239 +#endif
  1.3240 +               {
  1.3241 +                  sp = row;
  1.3242 +                  dp = row;
  1.3243 +                  for (i = 0; i < row_width; i++, sp += 4, dp += 3)
  1.3244 +                  {
  1.3245 +                     png_byte a = *(sp + 3);
  1.3246 +
  1.3247 +                     if (a == 0xff)
  1.3248 +                     {
  1.3249 +                        *dp = *sp;
  1.3250 +                        *(dp + 1) = *(sp + 1);
  1.3251 +                        *(dp + 2) = *(sp + 2);
  1.3252 +                     }
  1.3253 +                     else if (a == 0)
  1.3254 +                     {
  1.3255 +                        *dp = (png_byte)background->red;
  1.3256 +                        *(dp + 1) = (png_byte)background->green;
  1.3257 +                        *(dp + 2) = (png_byte)background->blue;
  1.3258 +                     }
  1.3259 +                     else
  1.3260 +                     {
  1.3261 +                        png_composite(*dp, *sp, a, background->red);
  1.3262 +                        png_composite(*(dp + 1), *(sp + 1), a,
  1.3263 +                           background->green);
  1.3264 +                        png_composite(*(dp + 2), *(sp + 2), a,
  1.3265 +                           background->blue);
  1.3266 +                     }
  1.3267 +                  }
  1.3268 +               }
  1.3269 +            }
  1.3270 +            else /* if (row_info->bit_depth == 16) */
  1.3271 +            {
  1.3272 +#if defined(PNG_READ_GAMMA_SUPPORTED)
  1.3273 +               if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
  1.3274 +                   gamma_16_to_1 != NULL)
  1.3275 +               {
  1.3276 +                  sp = row;
  1.3277 +                  dp = row;
  1.3278 +                  for (i = 0; i < row_width; i++, sp += 8, dp += 6)
  1.3279 +                  {
  1.3280 +                     png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
  1.3281 +                         << 8) + (png_uint_16)(*(sp + 7)));
  1.3282 +                     if (a == (png_uint_16)0xffff)
  1.3283 +                     {
  1.3284 +                        png_uint_16 v;
  1.3285 +
  1.3286 +                        v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
  1.3287 +                        *dp = (png_byte)((v >> 8) & 0xff);
  1.3288 +                        *(dp + 1) = (png_byte)(v & 0xff);
  1.3289 +                        v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
  1.3290 +                        *(dp + 2) = (png_byte)((v >> 8) & 0xff);
  1.3291 +                        *(dp + 3) = (png_byte)(v & 0xff);
  1.3292 +                        v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
  1.3293 +                        *(dp + 4) = (png_byte)((v >> 8) & 0xff);
  1.3294 +                        *(dp + 5) = (png_byte)(v & 0xff);
  1.3295 +                     }
  1.3296 +                     else if (a == 0)
  1.3297 +                     {
  1.3298 +                        /* background is already in screen gamma */
  1.3299 +                        *dp = (png_byte)((background->red >> 8) & 0xff);
  1.3300 +                        *(dp + 1) = (png_byte)(background->red & 0xff);
  1.3301 +                        *(dp + 2) = (png_byte)((background->green >> 8) & 0xff);
  1.3302 +                        *(dp + 3) = (png_byte)(background->green & 0xff);
  1.3303 +                        *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff);
  1.3304 +                        *(dp + 5) = (png_byte)(background->blue & 0xff);
  1.3305 +                     }
  1.3306 +                     else
  1.3307 +                     {
  1.3308 +                        png_uint_16 v, w, x;
  1.3309 +
  1.3310 +                        v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
  1.3311 +                        png_composite_16(w, v, a, background_1->red);
  1.3312 +                        x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
  1.3313 +                        *dp = (png_byte)((x >> 8) & 0xff);
  1.3314 +                        *(dp + 1) = (png_byte)(x & 0xff);
  1.3315 +                        v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)];
  1.3316 +                        png_composite_16(w, v, a, background_1->green);
  1.3317 +                        x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
  1.3318 +                        *(dp + 2) = (png_byte)((x >> 8) & 0xff);
  1.3319 +                        *(dp + 3) = (png_byte)(x & 0xff);
  1.3320 +                        v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)];
  1.3321 +                        png_composite_16(w, v, a, background_1->blue);
  1.3322 +                        x = gamma_16_from_1[(w & 0xff) >> gamma_shift][w >> 8];
  1.3323 +                        *(dp + 4) = (png_byte)((x >> 8) & 0xff);
  1.3324 +                        *(dp + 5) = (png_byte)(x & 0xff);
  1.3325 +                     }
  1.3326 +                  }
  1.3327 +               }
  1.3328 +               else
  1.3329 +#endif
  1.3330 +               {
  1.3331 +                  sp = row;
  1.3332 +                  dp = row;
  1.3333 +                  for (i = 0; i < row_width; i++, sp += 8, dp += 6)
  1.3334 +                  {
  1.3335 +                     png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
  1.3336 +                        << 8) + (png_uint_16)(*(sp + 7)));
  1.3337 +                     if (a == (png_uint_16)0xffff)
  1.3338 +                     {
  1.3339 +                        png_memcpy(dp, sp, 6);
  1.3340 +                     }
  1.3341 +                     else if (a == 0)
  1.3342 +                     {
  1.3343 +                        *dp = (png_byte)((background->red >> 8) & 0xff);
  1.3344 +                        *(dp + 1) = (png_byte)(background->red & 0xff);
  1.3345 +                        *(dp + 2) = (png_byte)((background->green >> 8) & 0xff);
  1.3346 +                        *(dp + 3) = (png_byte)(background->green & 0xff);
  1.3347 +                        *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff);
  1.3348 +                        *(dp + 5) = (png_byte)(background->blue & 0xff);
  1.3349 +                     }
  1.3350 +                     else
  1.3351 +                     {
  1.3352 +                        png_uint_16 v;
  1.3353 +
  1.3354 +                        png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
  1.3355 +                        png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
  1.3356 +                            + *(sp + 3));
  1.3357 +                        png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
  1.3358 +                            + *(sp + 5));
  1.3359 +
  1.3360 +                        png_composite_16(v, r, a, background->red);
  1.3361 +                        *dp = (png_byte)((v >> 8) & 0xff);
  1.3362 +                        *(dp + 1) = (png_byte)(v & 0xff);
  1.3363 +                        png_composite_16(v, g, a, background->green);
  1.3364 +                        *(dp + 2) = (png_byte)((v >> 8) & 0xff);
  1.3365 +                        *(dp + 3) = (png_byte)(v & 0xff);
  1.3366 +                        png_composite_16(v, b, a, background->blue);
  1.3367 +                        *(dp + 4) = (png_byte)((v >> 8) & 0xff);
  1.3368 +                        *(dp + 5) = (png_byte)(v & 0xff);
  1.3369 +                     }
  1.3370 +                  }
  1.3371 +               }
  1.3372 +            }
  1.3373 +            break;
  1.3374 +         }
  1.3375 +      }
  1.3376 +
  1.3377 +      if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
  1.3378 +      {
  1.3379 +         row_info->color_type &= ~PNG_COLOR_MASK_ALPHA;
  1.3380 +         row_info->channels--;
  1.3381 +         row_info->pixel_depth = (png_byte)(row_info->channels *
  1.3382 +            row_info->bit_depth);
  1.3383 +         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
  1.3384 +      }
  1.3385 +   }
  1.3386 +}
  1.3387 +#endif
  1.3388 +
  1.3389 +#if defined(PNG_READ_GAMMA_SUPPORTED)
  1.3390 +/* Gamma correct the image, avoiding the alpha channel.  Make sure
  1.3391 + * you do this after you deal with the transparency issue on grayscale
  1.3392 + * or RGB images. If your bit depth is 8, use gamma_table, if it
  1.3393 + * is 16, use gamma_16_table and gamma_shift.  Build these with
  1.3394 + * build_gamma_table().
  1.3395 + */
  1.3396 +void /* PRIVATE */
  1.3397 +png_do_gamma(png_row_infop row_info, png_bytep row,
  1.3398 +   png_bytep gamma_table, png_uint_16pp gamma_16_table,
  1.3399 +   int gamma_shift)
  1.3400 +{
  1.3401 +   png_bytep sp;
  1.3402 +   png_uint_32 i;
  1.3403 +   png_uint_32 row_width=row_info->width;
  1.3404 +
  1.3405 +   png_debug(1, "in png_do_gamma\n");
  1.3406 +   if (
  1.3407 +#if defined(PNG_USELESS_TESTS_SUPPORTED)
  1.3408 +       row != NULL && row_info != NULL &&
  1.3409 +#endif
  1.3410 +       ((row_info->bit_depth <= 8 && gamma_table != NULL) ||
  1.3411 +        (row_info->bit_depth == 16 && gamma_16_table != NULL)))
  1.3412 +   {
  1.3413 +      switch (row_info->color_type)
  1.3414 +      {
  1.3415 +         case PNG_COLOR_TYPE_RGB:
  1.3416 +         {
  1.3417 +            if (row_info->bit_depth == 8)
  1.3418 +            {
  1.3419 +               sp = row;
  1.3420 +               for (i = 0; i < row_width; i++)
  1.3421 +               {
  1.3422 +                  *sp = gamma_table[*sp];
  1.3423 +                  sp++;
  1.3424 +                  *sp = gamma_table[*sp];
  1.3425 +                  sp++;
  1.3426 +                  *sp = gamma_table[*sp];
  1.3427 +                  sp++;
  1.3428 +               }
  1.3429 +            }
  1.3430 +            else /* if (row_info->bit_depth == 16) */
  1.3431 +            {
  1.3432 +               sp = row;
  1.3433 +               for (i = 0; i < row_width; i++)
  1.3434 +               {
  1.3435 +                  png_uint_16 v;
  1.3436 +
  1.3437 +                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
  1.3438 +                  *sp = (png_byte)((v >> 8) & 0xff);
  1.3439 +                  *(sp + 1) = (png_byte)(v & 0xff);
  1.3440 +                  sp += 2;
  1.3441 +                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
  1.3442 +                  *sp = (png_byte)((v >> 8) & 0xff);
  1.3443 +                  *(sp + 1) = (png_byte)(v & 0xff);
  1.3444 +                  sp += 2;
  1.3445 +                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
  1.3446 +                  *sp = (png_byte)((v >> 8) & 0xff);
  1.3447 +                  *(sp + 1) = (png_byte)(v & 0xff);
  1.3448 +                  sp += 2;
  1.3449 +               }
  1.3450 +            }
  1.3451 +            break;
  1.3452 +         }
  1.3453 +         case PNG_COLOR_TYPE_RGB_ALPHA:
  1.3454 +         {
  1.3455 +            if (row_info->bit_depth == 8)
  1.3456 +            {
  1.3457 +               sp = row;
  1.3458 +               for (i = 0; i < row_width; i++)
  1.3459 +               {
  1.3460 +                  *sp = gamma_table[*sp];
  1.3461 +                  sp++;
  1.3462 +                  *sp = gamma_table[*sp];
  1.3463 +                  sp++;
  1.3464 +                  *sp = gamma_table[*sp];
  1.3465 +                  sp++;
  1.3466 +                  sp++;
  1.3467 +               }
  1.3468 +            }
  1.3469 +            else /* if (row_info->bit_depth == 16) */
  1.3470 +            {
  1.3471 +               sp = row;
  1.3472 +               for (i = 0; i < row_width; i++)
  1.3473 +               {
  1.3474 +                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
  1.3475 +                  *sp = (png_byte)((v >> 8) & 0xff);
  1.3476 +                  *(sp + 1) = (png_byte)(v & 0xff);
  1.3477 +                  sp += 2;
  1.3478 +                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
  1.3479 +                  *sp = (png_byte)((v >> 8) & 0xff);
  1.3480 +                  *(sp + 1) = (png_byte)(v & 0xff);
  1.3481 +                  sp += 2;
  1.3482 +                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
  1.3483 +                  *sp = (png_byte)((v >> 8) & 0xff);
  1.3484 +                  *(sp + 1) = (png_byte)(v & 0xff);
  1.3485 +                  sp += 4;
  1.3486 +               }
  1.3487 +            }
  1.3488 +            break;
  1.3489 +         }
  1.3490 +         case PNG_COLOR_TYPE_GRAY_ALPHA:
  1.3491 +         {
  1.3492 +            if (row_info->bit_depth == 8)
  1.3493 +            {
  1.3494 +               sp = row;
  1.3495 +               for (i = 0; i < row_width; i++)
  1.3496 +               {
  1.3497 +                  *sp = gamma_table[*sp];
  1.3498 +                  sp += 2;
  1.3499 +               }
  1.3500 +            }
  1.3501 +            else /* if (row_info->bit_depth == 16) */
  1.3502 +            {
  1.3503 +               sp = row;
  1.3504 +               for (i = 0; i < row_width; i++)
  1.3505 +               {
  1.3506 +                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
  1.3507 +                  *sp = (png_byte)((v >> 8) & 0xff);
  1.3508 +                  *(sp + 1) = (png_byte)(v & 0xff);
  1.3509 +                  sp += 4;
  1.3510 +               }
  1.3511 +            }
  1.3512 +            break;
  1.3513 +         }
  1.3514 +         case PNG_COLOR_TYPE_GRAY:
  1.3515 +         {
  1.3516 +            if (row_info->bit_depth == 2)
  1.3517 +            {
  1.3518 +               sp = row;
  1.3519 +               for (i = 0; i < row_width; i += 4)
  1.3520 +               {
  1.3521 +                  int a = *sp & 0xc0;
  1.3522 +                  int b = *sp & 0x30;
  1.3523 +                  int c = *sp & 0x0c;
  1.3524 +                  int d = *sp & 0x03;
  1.3525 +
  1.3526 +                  *sp = (png_byte)(
  1.3527 +                        ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)])   ) & 0xc0)|
  1.3528 +                        ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)|
  1.3529 +                        ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)|
  1.3530 +                        ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) ));
  1.3531 +                  sp++;
  1.3532 +               }
  1.3533 +            }
  1.3534 +            if (row_info->bit_depth == 4)
  1.3535 +            {
  1.3536 +               sp = row;
  1.3537 +               for (i = 0; i < row_width; i += 2)
  1.3538 +               {
  1.3539 +                  int msb = *sp & 0xf0;
  1.3540 +                  int lsb = *sp & 0x0f;
  1.3541 +
  1.3542 +                  *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0)
  1.3543 +                          | (((int)gamma_table[(lsb << 4) | lsb]) >> 4));
  1.3544 +                  sp++;
  1.3545 +               }
  1.3546 +            }
  1.3547 +            else if (row_info->bit_depth == 8)
  1.3548 +            {
  1.3549 +               sp = row;
  1.3550 +               for (i = 0; i < row_width; i++)
  1.3551 +               {
  1.3552 +                  *sp = gamma_table[*sp];
  1.3553 +                  sp++;
  1.3554 +               }
  1.3555 +            }
  1.3556 +            else if (row_info->bit_depth == 16)
  1.3557 +            {
  1.3558 +               sp = row;
  1.3559 +               for (i = 0; i < row_width; i++)
  1.3560 +               {
  1.3561 +                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
  1.3562 +                  *sp = (png_byte)((v >> 8) & 0xff);
  1.3563 +                  *(sp + 1) = (png_byte)(v & 0xff);
  1.3564 +                  sp += 2;
  1.3565 +               }
  1.3566 +            }
  1.3567 +            break;
  1.3568 +         }
  1.3569 +      }
  1.3570 +   }
  1.3571 +}
  1.3572 +#endif
  1.3573 +
  1.3574 +#if defined(PNG_READ_EXPAND_SUPPORTED)
  1.3575 +/* Expands a palette row to an RGB or RGBA row depending
  1.3576 + * upon whether you supply trans and num_trans.
  1.3577 + */
  1.3578 +void /* PRIVATE */
  1.3579 +png_do_expand_palette(png_row_infop row_info, png_bytep row,
  1.3580 +   png_colorp palette, png_bytep trans, int num_trans)
  1.3581 +{
  1.3582 +   int shift, value;
  1.3583 +   png_bytep sp, dp;
  1.3584 +   png_uint_32 i;
  1.3585 +   png_uint_32 row_width=row_info->width;
  1.3586 +
  1.3587 +   png_debug(1, "in png_do_expand_palette\n");
  1.3588 +   if (
  1.3589 +#if defined(PNG_USELESS_TESTS_SUPPORTED)
  1.3590 +       row != NULL && row_info != NULL &&
  1.3591 +#endif
  1.3592 +       row_info->color_type == PNG_COLOR_TYPE_PALETTE)
  1.3593 +   {
  1.3594 +      if (row_info->bit_depth < 8)
  1.3595 +      {
  1.3596 +         switch (row_info->bit_depth)
  1.3597 +         {
  1.3598 +            case 1:
  1.3599 +            {
  1.3600 +               sp = row + (png_size_t)((row_width - 1) >> 3);
  1.3601 +               dp = row + (png_size_t)row_width - 1;
  1.3602 +               shift = 7 - (int)((row_width + 7) & 0x07);
  1.3603 +               for (i = 0; i < row_width; i++)
  1.3604 +               {
  1.3605 +                  if ((*sp >> shift) & 0x01)
  1.3606 +                     *dp = 1;
  1.3607 +                  else
  1.3608 +                     *dp = 0;
  1.3609 +                  if (shift == 7)
  1.3610 +                  {
  1.3611 +                     shift = 0;
  1.3612 +                     sp--;
  1.3613 +                  }
  1.3614 +                  else
  1.3615 +                     shift++;
  1.3616 +
  1.3617 +                  dp--;
  1.3618 +               }
  1.3619 +               break;
  1.3620 +            }
  1.3621 +            case 2:
  1.3622 +            {
  1.3623 +               sp = row + (png_size_t)((row_width - 1) >> 2);
  1.3624 +               dp = row + (png_size_t)row_width - 1;
  1.3625 +               shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
  1.3626 +               for (i = 0; i < row_width; i++)
  1.3627 +               {
  1.3628 +                  value = (*sp >> shift) & 0x03;
  1.3629 +                  *dp = (png_byte)value;
  1.3630 +                  if (shift == 6)
  1.3631 +                  {
  1.3632 +                     shift = 0;
  1.3633 +                     sp--;
  1.3634 +                  }
  1.3635 +                  else
  1.3636 +                     shift += 2;
  1.3637 +
  1.3638 +                  dp--;
  1.3639 +               }
  1.3640 +               break;
  1.3641 +            }
  1.3642 +            case 4:
  1.3643 +            {
  1.3644 +               sp = row + (png_size_t)((row_width - 1) >> 1);
  1.3645 +               dp = row + (png_size_t)row_width - 1;
  1.3646 +               shift = (int)((row_width & 0x01) << 2);
  1.3647 +               for (i = 0; i < row_width; i++)
  1.3648 +               {
  1.3649 +                  value = (*sp >> shift) & 0x0f;
  1.3650 +                  *dp = (png_byte)value;
  1.3651 +                  if (shift == 4)
  1.3652 +                  {
  1.3653 +                     shift = 0;
  1.3654 +                     sp--;
  1.3655 +                  }
  1.3656 +                  else
  1.3657 +                     shift += 4;
  1.3658 +
  1.3659 +                  dp--;
  1.3660 +               }
  1.3661 +               break;
  1.3662 +            }
  1.3663 +         }
  1.3664 +         row_info->bit_depth = 8;
  1.3665 +         row_info->pixel_depth = 8;
  1.3666 +         row_info->rowbytes = row_width;
  1.3667 +      }
  1.3668 +      switch (row_info->bit_depth)
  1.3669 +      {
  1.3670 +         case 8:
  1.3671 +         {
  1.3672 +            if (trans != NULL)
  1.3673 +            {
  1.3674 +               sp = row + (png_size_t)row_width - 1;
  1.3675 +               dp = row + (png_size_t)(row_width << 2) - 1;
  1.3676 +
  1.3677 +               for (i = 0; i < row_width; i++)
  1.3678 +               {
  1.3679 +                  if ((int)(*sp) >= num_trans)
  1.3680 +                     *dp-- = 0xff;
  1.3681 +                  else
  1.3682 +                     *dp-- = trans[*sp];
  1.3683 +                  *dp-- = palette[*sp].blue;
  1.3684 +                  *dp-- = palette[*sp].green;
  1.3685 +                  *dp-- = palette[*sp].red;
  1.3686 +                  sp--;
  1.3687 +               }
  1.3688 +               row_info->bit_depth = 8;
  1.3689 +               row_info->pixel_depth = 32;
  1.3690 +               row_info->rowbytes = row_width * 4;
  1.3691 +               row_info->color_type = 6;
  1.3692 +               row_info->channels = 4;
  1.3693 +            }
  1.3694 +            else
  1.3695 +            {
  1.3696 +               sp = row + (png_size_t)row_width - 1;
  1.3697 +               dp = row + (png_size_t)(row_width * 3) - 1;
  1.3698 +
  1.3699 +               for (i = 0; i < row_width; i++)
  1.3700 +               {
  1.3701 +                  *dp-- = palette[*sp].blue;
  1.3702 +                  *dp-- = palette[*sp].green;
  1.3703 +                  *dp-- = palette[*sp].red;
  1.3704 +                  sp--;
  1.3705 +               }
  1.3706 +               row_info->bit_depth = 8;
  1.3707 +               row_info->pixel_depth = 24;
  1.3708 +               row_info->rowbytes = row_width * 3;
  1.3709 +               row_info->color_type = 2;
  1.3710 +               row_info->channels = 3;
  1.3711 +            }
  1.3712 +            break;
  1.3713 +         }
  1.3714 +      }
  1.3715 +   }
  1.3716 +}
  1.3717 +
  1.3718 +/* If the bit depth < 8, it is expanded to 8.  Also, if the already
  1.3719 + * expanded transparency value is supplied, an alpha channel is built.
  1.3720 + */
  1.3721 +void /* PRIVATE */
  1.3722 +png_do_expand(png_row_infop row_info, png_bytep row,
  1.3723 +   png_color_16p trans_value)
  1.3724 +{
  1.3725 +   int shift, value;
  1.3726 +   png_bytep sp, dp;
  1.3727 +   png_uint_32 i;
  1.3728 +   png_uint_32 row_width=row_info->width;
  1.3729 +
  1.3730 +   png_debug(1, "in png_do_expand\n");
  1.3731 +#if defined(PNG_USELESS_TESTS_SUPPORTED)
  1.3732 +   if (row != NULL && row_info != NULL)
  1.3733 +#endif
  1.3734 +   {
  1.3735 +      if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
  1.3736 +      {
  1.3737 +         png_uint_16 gray = (png_uint_16)(trans_value ? trans_value->gray : 0);
  1.3738 +
  1.3739 +         if (row_info->bit_depth < 8)
  1.3740 +         {
  1.3741 +            switch (row_info->bit_depth)
  1.3742 +            {
  1.3743 +               case 1:
  1.3744 +               {
  1.3745 +                  gray = (png_uint_16)((gray&0x01)*0xff);
  1.3746 +                  sp = row + (png_size_t)((row_width - 1) >> 3);
  1.3747 +                  dp = row + (png_size_t)row_width - 1;
  1.3748 +                  shift = 7 - (int)((row_width + 7) & 0x07);
  1.3749 +                  for (i = 0; i < row_width; i++)
  1.3750 +                  {
  1.3751 +                     if ((*sp >> shift) & 0x01)
  1.3752 +                        *dp = 0xff;
  1.3753 +                     else
  1.3754 +                        *dp = 0;
  1.3755 +                     if (shift == 7)
  1.3756 +                     {
  1.3757 +                        shift = 0;
  1.3758 +                        sp--;
  1.3759 +                     }
  1.3760 +                     else
  1.3761 +                        shift++;
  1.3762 +
  1.3763 +                     dp--;
  1.3764 +                  }
  1.3765 +                  break;
  1.3766 +               }
  1.3767 +               case 2:
  1.3768 +               {
  1.3769 +                  gray = (png_uint_16)((gray&0x03)*0x55);
  1.3770 +                  sp = row + (png_size_t)((row_width - 1) >> 2);
  1.3771 +                  dp = row + (png_size_t)row_width - 1;
  1.3772 +                  shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
  1.3773 +                  for (i = 0; i < row_width; i++)
  1.3774 +                  {
  1.3775 +                     value = (*sp >> shift) & 0x03;
  1.3776 +                     *dp = (png_byte)(value | (value << 2) | (value << 4) |
  1.3777 +                        (value << 6));
  1.3778 +                     if (shift == 6)
  1.3779 +                     {
  1.3780 +                        shift = 0;
  1.3781 +                        sp--;
  1.3782 +                     }
  1.3783 +                     else
  1.3784 +                        shift += 2;
  1.3785 +
  1.3786 +                     dp--;
  1.3787 +                  }
  1.3788 +                  break;
  1.3789 +               }
  1.3790 +               case 4:
  1.3791 +               {
  1.3792 +                  gray = (png_uint_16)((gray&0x0f)*0x11);
  1.3793 +                  sp = row + (png_size_t)((row_width - 1) >> 1);
  1.3794 +                  dp = row + (png_size_t)row_width - 1;
  1.3795 +                  shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
  1.3796 +                  for (i = 0; i < row_width; i++)
  1.3797 +                  {
  1.3798 +                     value = (*sp >> shift) & 0x0f;
  1.3799 +                     *dp = (png_byte)(value | (value << 4));
  1.3800 +                     if (shift == 4)
  1.3801 +                     {
  1.3802 +                        shift = 0;
  1.3803 +                        sp--;
  1.3804 +                     }
  1.3805 +                     else
  1.3806 +                        shift = 4;
  1.3807 +
  1.3808 +                     dp--;
  1.3809 +                  }
  1.3810 +                  break;
  1.3811 +               }
  1.3812 +            }
  1.3813 +            row_info->bit_depth = 8;
  1.3814 +            row_info->pixel_depth = 8;
  1.3815 +            row_info->rowbytes = row_width;
  1.3816 +         }
  1.3817 +
  1.3818 +         if (trans_value != NULL)
  1.3819 +         {
  1.3820 +            if (row_info->bit_depth == 8)
  1.3821 +            {
  1.3822 +               gray = gray & 0xff;
  1.3823 +               sp = row + (png_size_t)row_width - 1;
  1.3824 +               dp = row + (png_size_t)(row_width << 1) - 1;
  1.3825 +               for (i = 0; i < row_width; i++)
  1.3826 +               {
  1.3827 +                  if (*sp == gray)
  1.3828 +                     *dp-- = 0;
  1.3829 +                  else
  1.3830 +                     *dp-- = 0xff;
  1.3831 +                  *dp-- = *sp--;
  1.3832 +               }
  1.3833 +            }
  1.3834 +            else if (row_info->bit_depth == 16)
  1.3835 +            {
  1.3836 +               png_byte gray_high = (gray >> 8) & 0xff;
  1.3837 +               png_byte gray_low = gray & 0xff;
  1.3838 +               sp = row + row_info->rowbytes - 1;
  1.3839 +               dp = row + (row_info->rowbytes << 1) - 1;
  1.3840 +               for (i = 0; i < row_width; i++)
  1.3841 +               {
  1.3842 +                  if (*(sp - 1) == gray_high && *(sp) == gray_low) 
  1.3843 +                  {
  1.3844 +                     *dp-- = 0;
  1.3845 +                     *dp-- = 0;
  1.3846 +                  }
  1.3847 +                  else
  1.3848 +                  {
  1.3849 +                     *dp-- = 0xff;
  1.3850 +                     *dp-- = 0xff;
  1.3851 +                  }
  1.3852 +                  *dp-- = *sp--;
  1.3853 +                  *dp-- = *sp--;
  1.3854 +               }
  1.3855 +            }
  1.3856 +            row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
  1.3857 +            row_info->channels = 2;
  1.3858 +            row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1);
  1.3859 +            row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
  1.3860 +               row_width);
  1.3861 +         }
  1.3862 +      }
  1.3863 +      else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_value)
  1.3864 +      {
  1.3865 +         if (row_info->bit_depth == 8)
  1.3866 +         {
  1.3867 +            png_byte red = trans_value->red & 0xff;
  1.3868 +            png_byte green = trans_value->green & 0xff;
  1.3869 +            png_byte blue = trans_value->blue & 0xff;
  1.3870 +            sp = row + (png_size_t)row_info->rowbytes - 1;
  1.3871 +            dp = row + (png_size_t)(row_width << 2) - 1;
  1.3872 +            for (i = 0; i < row_width; i++)
  1.3873 +            {
  1.3874 +               if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue)
  1.3875 +                  *dp-- = 0;
  1.3876 +               else
  1.3877 +                  *dp-- = 0xff;
  1.3878 +               *dp-- = *sp--;
  1.3879 +               *dp-- = *sp--;
  1.3880 +               *dp-- = *sp--;
  1.3881 +            }
  1.3882 +         }
  1.3883 +         else if (row_info->bit_depth == 16)
  1.3884 +         {
  1.3885 +            png_byte red_high = (trans_value->red >> 8) & 0xff;
  1.3886 +            png_byte green_high = (trans_value->green >> 8) & 0xff;
  1.3887 +            png_byte blue_high = (trans_value->blue >> 8) & 0xff;
  1.3888 +            png_byte red_low = trans_value->red & 0xff;
  1.3889 +            png_byte green_low = trans_value->green & 0xff;
  1.3890 +            png_byte blue_low = trans_value->blue & 0xff;
  1.3891 +            sp = row + row_info->rowbytes - 1;
  1.3892 +            dp = row + (png_size_t)(row_width << 3) - 1;
  1.3893 +            for (i = 0; i < row_width; i++)
  1.3894 +            {
  1.3895 +               if (*(sp - 5) == red_high &&
  1.3896 +                  *(sp - 4) == red_low &&
  1.3897 +                  *(sp - 3) == green_high &&
  1.3898 +                  *(sp - 2) == green_low &&
  1.3899 +                  *(sp - 1) == blue_high &&
  1.3900 +                  *(sp    ) == blue_low)
  1.3901 +               {
  1.3902 +                  *dp-- = 0;
  1.3903 +                  *dp-- = 0;
  1.3904 +               }
  1.3905 +               else
  1.3906 +               {
  1.3907 +                  *dp-- = 0xff;
  1.3908 +                  *dp-- = 0xff;
  1.3909 +               }
  1.3910 +               *dp-- = *sp--;
  1.3911 +               *dp-- = *sp--;
  1.3912 +               *dp-- = *sp--;
  1.3913 +               *dp-- = *sp--;
  1.3914 +               *dp-- = *sp--;
  1.3915 +               *dp-- = *sp--;
  1.3916 +            }
  1.3917 +         }
  1.3918 +         row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
  1.3919 +         row_info->channels = 4;
  1.3920 +         row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2);
  1.3921 +         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
  1.3922 +      }
  1.3923 +   }
  1.3924 +}
  1.3925 +#endif
  1.3926 +
  1.3927 +#if defined(PNG_READ_DITHER_SUPPORTED)
  1.3928 +void /* PRIVATE */
  1.3929 +png_do_dither(png_row_infop row_info, png_bytep row,
  1.3930 +    png_bytep palette_lookup, png_bytep dither_lookup)
  1.3931 +{
  1.3932 +   png_bytep sp, dp;
  1.3933 +   png_uint_32 i;
  1.3934 +   png_uint_32 row_width=row_info->width;
  1.3935 +
  1.3936 +   png_debug(1, "in png_do_dither\n");
  1.3937 +#if defined(PNG_USELESS_TESTS_SUPPORTED)
  1.3938 +   if (row != NULL && row_info != NULL)
  1.3939 +#endif
  1.3940 +   {
  1.3941 +      if (row_info->color_type == PNG_COLOR_TYPE_RGB &&
  1.3942 +         palette_lookup && row_info->bit_depth == 8)
  1.3943 +      {
  1.3944 +         int r, g, b, p;
  1.3945 +         sp = row;
  1.3946 +         dp = row;
  1.3947 +         for (i = 0; i < row_width; i++)
  1.3948 +         {
  1.3949 +            r = *sp++;
  1.3950 +            g = *sp++;
  1.3951 +            b = *sp++;
  1.3952 +
  1.3953 +            /* this looks real messy, but the compiler will reduce
  1.3954 +               it down to a reasonable formula.  For example, with
  1.3955 +               5 bits per color, we get:
  1.3956 +               p = (((r >> 3) & 0x1f) << 10) |
  1.3957 +                  (((g >> 3) & 0x1f) << 5) |
  1.3958 +                  ((b >> 3) & 0x1f);
  1.3959 +               */
  1.3960 +            p = (((r >> (8 - PNG_DITHER_RED_BITS)) &
  1.3961 +               ((1 << PNG_DITHER_RED_BITS) - 1)) <<
  1.3962 +               (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) |
  1.3963 +               (((g >> (8 - PNG_DITHER_GREEN_BITS)) &
  1.3964 +               ((1 << PNG_DITHER_GREEN_BITS) - 1)) <<
  1.3965 +               (PNG_DITHER_BLUE_BITS)) |
  1.3966 +               ((b >> (8 - PNG_DITHER_BLUE_BITS)) &
  1.3967 +               ((1 << PNG_DITHER_BLUE_BITS) - 1));
  1.3968 +
  1.3969 +            *dp++ = palette_lookup[p];
  1.3970 +         }
  1.3971 +         row_info->color_type = PNG_COLOR_TYPE_PALETTE;
  1.3972 +         row_info->channels = 1;
  1.3973 +         row_info->pixel_depth = row_info->bit_depth;
  1.3974 +         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
  1.3975 +      }
  1.3976 +      else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
  1.3977 +         palette_lookup != NULL && row_info->bit_depth == 8)
  1.3978 +      {
  1.3979 +         int r, g, b, p;
  1.3980 +         sp = row;
  1.3981 +         dp = row;
  1.3982 +         for (i = 0; i < row_width; i++)
  1.3983 +         {
  1.3984 +            r = *sp++;
  1.3985 +            g = *sp++;
  1.3986 +            b = *sp++;
  1.3987 +            sp++;
  1.3988 +
  1.3989 +            p = (((r >> (8 - PNG_DITHER_RED_BITS)) &
  1.3990 +               ((1 << PNG_DITHER_RED_BITS) - 1)) <<
  1.3991 +               (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) |
  1.3992 +               (((g >> (8 - PNG_DITHER_GREEN_BITS)) &
  1.3993 +               ((1 << PNG_DITHER_GREEN_BITS) - 1)) <<
  1.3994 +               (PNG_DITHER_BLUE_BITS)) |
  1.3995 +               ((b >> (8 - PNG_DITHER_BLUE_BITS)) &
  1.3996 +               ((1 << PNG_DITHER_BLUE_BITS) - 1));
  1.3997 +
  1.3998 +            *dp++ = palette_lookup[p];
  1.3999 +         }
  1.4000 +         row_info->color_type = PNG_COLOR_TYPE_PALETTE;
  1.4001 +         row_info->channels = 1;
  1.4002 +         row_info->pixel_depth = row_info->bit_depth;
  1.4003 +         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
  1.4004 +      }
  1.4005 +      else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
  1.4006 +         dither_lookup && row_info->bit_depth == 8)
  1.4007 +      {
  1.4008 +         sp = row;
  1.4009 +         for (i = 0; i < row_width; i++, sp++)
  1.4010 +         {
  1.4011 +            *sp = dither_lookup[*sp];
  1.4012 +         }
  1.4013 +      }
  1.4014 +   }
  1.4015 +}
  1.4016 +#endif
  1.4017 +
  1.4018 +#ifdef PNG_FLOATING_POINT_SUPPORTED
  1.4019 +#if defined(PNG_READ_GAMMA_SUPPORTED)
  1.4020 +static PNG_CONST int png_gamma_shift[] =
  1.4021 +   {0x10, 0x21, 0x42, 0x84, 0x110, 0x248, 0x550, 0xff0, 0x00};
  1.4022 +
  1.4023 +/* We build the 8- or 16-bit gamma tables here.  Note that for 16-bit
  1.4024 + * tables, we don't make a full table if we are reducing to 8-bit in
  1.4025 + * the future.  Note also how the gamma_16 tables are segmented so that
  1.4026 + * we don't need to allocate > 64K chunks for a full 16-bit table.
  1.4027 + */
  1.4028 +void /* PRIVATE */
  1.4029 +png_build_gamma_table(png_structp png_ptr)
  1.4030 +{
  1.4031 +  png_debug(1, "in png_build_gamma_table\n");
  1.4032 +
  1.4033 +  if (png_ptr->bit_depth <= 8)
  1.4034 +  {
  1.4035 +     int i;
  1.4036 +     double g;
  1.4037 +
  1.4038 +     if (png_ptr->screen_gamma > .000001)
  1.4039 +        g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
  1.4040 +     else
  1.4041 +        g = 1.0;
  1.4042 +
  1.4043 +     png_ptr->gamma_table = (png_bytep)png_malloc(png_ptr,
  1.4044 +        (png_uint_32)256);
  1.4045 +
  1.4046 +     for (i = 0; i < 256; i++)
  1.4047 +     {
  1.4048 +        png_ptr->gamma_table[i] = (png_byte)(pow((double)i / 255.0,
  1.4049 +           g) * 255.0 + .5);
  1.4050 +     }
  1.4051 +
  1.4052 +#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
  1.4053 +   defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
  1.4054 +     if (png_ptr->transformations & ((PNG_BACKGROUND) | PNG_RGB_TO_GRAY))
  1.4055 +     {
  1.4056 +
  1.4057 +        g = 1.0 / (png_ptr->gamma);
  1.4058 +
  1.4059 +        png_ptr->gamma_to_1 = (png_bytep)png_malloc(png_ptr,
  1.4060 +           (png_uint_32)256);
  1.4061 +
  1.4062 +        for (i = 0; i < 256; i++)
  1.4063 +        {
  1.4064 +           png_ptr->gamma_to_1[i] = (png_byte)(pow((double)i / 255.0,
  1.4065 +              g) * 255.0 + .5);
  1.4066 +        }
  1.4067 +
  1.4068 +
  1.4069 +        png_ptr->gamma_from_1 = (png_bytep)png_malloc(png_ptr,
  1.4070 +           (png_uint_32)256);
  1.4071 +
  1.4072 +        if (png_ptr->screen_gamma > 0.000001)
  1.4073 +           g = 1.0 / png_ptr->screen_gamma;
  1.4074 +        else
  1.4075 +           g = png_ptr->gamma;   /* probably doing rgb_to_gray */
  1.4076 +
  1.4077 +        for (i = 0; i < 256; i++)
  1.4078 +        {
  1.4079 +           png_ptr->gamma_from_1[i] = (png_byte)(pow((double)i / 255.0,
  1.4080 +              g) * 255.0 + .5);
  1.4081 +
  1.4082 +        }
  1.4083 +     }
  1.4084 +#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
  1.4085 +  }
  1.4086 +  else
  1.4087 +  {
  1.4088 +     double g;
  1.4089 +     int i, j, shift, num;
  1.4090 +     int sig_bit;
  1.4091 +     png_uint_32 ig;
  1.4092 +
  1.4093 +     if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
  1.4094 +     {
  1.4095 +        sig_bit = (int)png_ptr->sig_bit.red;
  1.4096 +        if ((int)png_ptr->sig_bit.green > sig_bit)
  1.4097 +           sig_bit = png_ptr->sig_bit.green;
  1.4098 +        if ((int)png_ptr->sig_bit.blue > sig_bit)
  1.4099 +           sig_bit = png_ptr->sig_bit.blue;
  1.4100 +     }
  1.4101 +     else
  1.4102 +     {
  1.4103 +        sig_bit = (int)png_ptr->sig_bit.gray;
  1.4104 +     }
  1.4105 +
  1.4106 +     if (sig_bit > 0)
  1.4107 +        shift = 16 - sig_bit;
  1.4108 +     else
  1.4109 +        shift = 0;
  1.4110 +
  1.4111 +     if (png_ptr->transformations & PNG_16_TO_8)
  1.4112 +     {
  1.4113 +        if (shift < (16 - PNG_MAX_GAMMA_8))
  1.4114 +           shift = (16 - PNG_MAX_GAMMA_8);
  1.4115 +     }
  1.4116 +
  1.4117 +     if (shift > 8)
  1.4118 +        shift = 8;
  1.4119 +     if (shift < 0)
  1.4120 +        shift = 0;
  1.4121 +
  1.4122 +     png_ptr->gamma_shift = (png_byte)shift;
  1.4123 +
  1.4124 +     num = (1 << (8 - shift));
  1.4125 +
  1.4126 +     if (png_ptr->screen_gamma > .000001)
  1.4127 +        g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
  1.4128 +     else
  1.4129 +        g = 1.0;
  1.4130 +
  1.4131 +     png_ptr->gamma_16_table = (png_uint_16pp)png_malloc(png_ptr,
  1.4132 +        (png_uint_32)(num * png_sizeof(png_uint_16p)));
  1.4133 +
  1.4134 +     if (png_ptr->transformations & (PNG_16_TO_8 | PNG_BACKGROUND))
  1.4135 +     {
  1.4136 +        double fin, fout;
  1.4137 +        png_uint_32 last, max;
  1.4138 +
  1.4139 +        for (i = 0; i < num; i++)
  1.4140 +        {
  1.4141 +           png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
  1.4142 +              (png_uint_32)(256 * png_sizeof(png_uint_16)));
  1.4143 +        }
  1.4144 +
  1.4145 +        g = 1.0 / g;
  1.4146 +        last = 0;
  1.4147 +        for (i = 0; i < 256; i++)
  1.4148 +        {
  1.4149 +           fout = ((double)i + 0.5) / 256.0;
  1.4150 +           fin = pow(fout, g);
  1.4151 +           max = (png_uint_32)(fin * (double)((png_uint_32)num << 8));
  1.4152 +           while (last <= max)
  1.4153 +           {
  1.4154 +              png_ptr->gamma_16_table[(int)(last & (0xff >> shift))]
  1.4155 +                 [(int)(last >> (8 - shift))] = (png_uint_16)(
  1.4156 +                 (png_uint_16)i | ((png_uint_16)i << 8));
  1.4157 +              last++;
  1.4158 +           }
  1.4159 +        }
  1.4160 +        while (last < ((png_uint_32)num << 8))
  1.4161 +        {
  1.4162 +           png_ptr->gamma_16_table[(int)(last & (0xff >> shift))]
  1.4163 +              [(int)(last >> (8 - shift))] = (png_uint_16)65535L;
  1.4164 +           last++;
  1.4165 +        }
  1.4166 +     }
  1.4167 +     else
  1.4168 +     {
  1.4169 +        for (i = 0; i < num; i++)
  1.4170 +        {
  1.4171 +           png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
  1.4172 +              (png_uint_32)(256 * png_sizeof(png_uint_16)));
  1.4173 +
  1.4174 +           ig = (((png_uint_32)i * (png_uint_32)png_gamma_shift[shift]) >> 4);
  1.4175 +           for (j = 0; j < 256; j++)
  1.4176 +           {
  1.4177 +              png_ptr->gamma_16_table[i][j] =
  1.4178 +                 (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
  1.4179 +                    65535.0, g) * 65535.0 + .5);
  1.4180 +           }
  1.4181 +        }
  1.4182 +     }
  1.4183 +
  1.4184 +#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
  1.4185 +   defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
  1.4186 +     if (png_ptr->transformations & (PNG_BACKGROUND | PNG_RGB_TO_GRAY))
  1.4187 +     {
  1.4188 +
  1.4189 +        g = 1.0 / (png_ptr->gamma);
  1.4190 +
  1.4191 +        png_ptr->gamma_16_to_1 = (png_uint_16pp)png_malloc(png_ptr,
  1.4192 +           (png_uint_32)(num * png_sizeof(png_uint_16p )));
  1.4193 +
  1.4194 +        for (i = 0; i < num; i++)
  1.4195 +        {
  1.4196 +           png_ptr->gamma_16_to_1[i] = (png_uint_16p)png_malloc(png_ptr,
  1.4197 +              (png_uint_32)(256 * png_sizeof(png_uint_16)));
  1.4198 +
  1.4199 +           ig = (((png_uint_32)i *
  1.4200 +              (png_uint_32)png_gamma_shift[shift]) >> 4);
  1.4201 +           for (j = 0; j < 256; j++)
  1.4202 +           {
  1.4203 +              png_ptr->gamma_16_to_1[i][j] =
  1.4204 +                 (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
  1.4205 +                    65535.0, g) * 65535.0 + .5);
  1.4206 +           }
  1.4207 +        }
  1.4208 +
  1.4209 +        if (png_ptr->screen_gamma > 0.000001)
  1.4210 +           g = 1.0 / png_ptr->screen_gamma;
  1.4211 +        else
  1.4212 +           g = png_ptr->gamma;   /* probably doing rgb_to_gray */
  1.4213 +
  1.4214 +        png_ptr->gamma_16_from_1 = (png_uint_16pp)png_malloc(png_ptr,
  1.4215 +           (png_uint_32)(num * png_sizeof(png_uint_16p)));
  1.4216 +
  1.4217 +        for (i = 0; i < num; i++)
  1.4218 +        {
  1.4219 +           png_ptr->gamma_16_from_1[i] = (png_uint_16p)png_malloc(png_ptr,
  1.4220 +              (png_uint_32)(256 * png_sizeof(png_uint_16)));
  1.4221 +
  1.4222 +           ig = (((png_uint_32)i *
  1.4223 +              (png_uint_32)png_gamma_shift[shift]) >> 4);
  1.4224 +           for (j = 0; j < 256; j++)
  1.4225 +           {
  1.4226 +              png_ptr->gamma_16_from_1[i][j] =
  1.4227 +                 (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
  1.4228 +                    65535.0, g) * 65535.0 + .5);
  1.4229 +           }
  1.4230 +        }
  1.4231 +     }
  1.4232 +#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
  1.4233 +  }
  1.4234 +}
  1.4235 +#endif
  1.4236 +/* To do: install integer version of png_build_gamma_table here */
  1.4237 +#endif
  1.4238 +
  1.4239 +#if defined(PNG_MNG_FEATURES_SUPPORTED)
  1.4240 +/* undoes intrapixel differencing  */
  1.4241 +void /* PRIVATE */
  1.4242 +png_do_read_intrapixel(png_row_infop row_info, png_bytep row)
  1.4243 +{
  1.4244 +   png_debug(1, "in png_do_read_intrapixel\n");
  1.4245 +   if (
  1.4246 +#if defined(PNG_USELESS_TESTS_SUPPORTED)
  1.4247 +       row != NULL && row_info != NULL &&
  1.4248 +#endif
  1.4249 +       (row_info->color_type & PNG_COLOR_MASK_COLOR))
  1.4250 +   {
  1.4251 +      int bytes_per_pixel;
  1.4252 +      png_uint_32 row_width = row_info->width;
  1.4253 +      if (row_info->bit_depth == 8)
  1.4254 +      {
  1.4255 +         png_bytep rp;
  1.4256 +         png_uint_32 i;
  1.4257 +
  1.4258 +         if (row_info->color_type == PNG_COLOR_TYPE_RGB)
  1.4259 +            bytes_per_pixel = 3;
  1.4260 +         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
  1.4261 +            bytes_per_pixel = 4;
  1.4262 +         else
  1.4263 +            return;
  1.4264 +
  1.4265 +         for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
  1.4266 +         {
  1.4267 +            *(rp) = (png_byte)((256 + *rp + *(rp+1))&0xff);
  1.4268 +            *(rp+2) = (png_byte)((256 + *(rp+2) + *(rp+1))&0xff);
  1.4269 +         }
  1.4270 +      }
  1.4271 +      else if (row_info->bit_depth == 16)
  1.4272 +      {
  1.4273 +         png_bytep rp;
  1.4274 +         png_uint_32 i;
  1.4275 +
  1.4276 +         if (row_info->color_type == PNG_COLOR_TYPE_RGB)
  1.4277 +            bytes_per_pixel = 6;
  1.4278 +         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
  1.4279 +            bytes_per_pixel = 8;
  1.4280 +         else
  1.4281 +            return;
  1.4282 +
  1.4283 +         for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
  1.4284 +         {
  1.4285 +            png_uint_32 s0   = (*(rp    ) << 8) | *(rp + 1);
  1.4286 +            png_uint_32 s1   = (*(rp + 2) << 8) | *(rp + 3);
  1.4287 +            png_uint_32 s2   = (*(rp + 4) << 8) | *(rp + 5);
  1.4288 +            png_uint_32 red  = (png_uint_32)((s0 + s1 + 65536L) & 0xffffL);
  1.4289 +            png_uint_32 blue = (png_uint_32)((s2 + s1 + 65536L) & 0xffffL);
  1.4290 +            *(rp  ) = (png_byte)((red >> 8) & 0xff);
  1.4291 +            *(rp+1) = (png_byte)(red & 0xff);
  1.4292 +            *(rp+4) = (png_byte)((blue >> 8) & 0xff);
  1.4293 +            *(rp+5) = (png_byte)(blue & 0xff);
  1.4294 +         }
  1.4295 +      }
  1.4296 +   }
  1.4297 +}
  1.4298 +#endif /* PNG_MNG_FEATURES_SUPPORTED */
  1.4299 +#endif /* PNG_READ_SUPPORTED */