media/libpng/pngrtran.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/media/libpng/pngrtran.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,4991 @@
     1.4 +
     1.5 +/* pngrtran.c - transforms the data in a row for PNG readers
     1.6 + *
     1.7 + * Last changed in libpng 1.6.10 [March 6, 2014]
     1.8 + * Copyright (c) 1998-2014 Glenn Randers-Pehrson
     1.9 + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
    1.10 + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
    1.11 + *
    1.12 + * This code is released under the libpng license.
    1.13 + * For conditions of distribution and use, see the disclaimer
    1.14 + * and license in png.h
    1.15 + *
    1.16 + * This file contains functions optionally called by an application
    1.17 + * in order to tell libpng how to handle data when reading a PNG.
    1.18 + * Transformations that are used in both reading and writing are
    1.19 + * in pngtrans.c.
    1.20 + */
    1.21 +
    1.22 +#include "pngpriv.h"
    1.23 +
    1.24 +#ifdef PNG_READ_SUPPORTED
    1.25 +
    1.26 +/* Set the action on getting a CRC error for an ancillary or critical chunk. */
    1.27 +void PNGAPI
    1.28 +png_set_crc_action(png_structrp png_ptr, int crit_action, int ancil_action)
    1.29 +{
    1.30 +   png_debug(1, "in png_set_crc_action");
    1.31 +
    1.32 +   if (png_ptr == NULL)
    1.33 +      return;
    1.34 +
    1.35 +   /* Tell libpng how we react to CRC errors in critical chunks */
    1.36 +   switch (crit_action)
    1.37 +   {
    1.38 +      case PNG_CRC_NO_CHANGE:                        /* Leave setting as is */
    1.39 +         break;
    1.40 +
    1.41 +      case PNG_CRC_WARN_USE:                               /* Warn/use data */
    1.42 +         png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
    1.43 +         png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE;
    1.44 +         break;
    1.45 +
    1.46 +      case PNG_CRC_QUIET_USE:                             /* Quiet/use data */
    1.47 +         png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
    1.48 +         png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE |
    1.49 +                           PNG_FLAG_CRC_CRITICAL_IGNORE;
    1.50 +         break;
    1.51 +
    1.52 +      case PNG_CRC_WARN_DISCARD:    /* Not a valid action for critical data */
    1.53 +         png_warning(png_ptr,
    1.54 +            "Can't discard critical data on CRC error");
    1.55 +      case PNG_CRC_ERROR_QUIT:                                /* Error/quit */
    1.56 +
    1.57 +      case PNG_CRC_DEFAULT:
    1.58 +      default:
    1.59 +         png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
    1.60 +         break;
    1.61 +   }
    1.62 +
    1.63 +   /* Tell libpng how we react to CRC errors in ancillary chunks */
    1.64 +   switch (ancil_action)
    1.65 +   {
    1.66 +      case PNG_CRC_NO_CHANGE:                       /* Leave setting as is */
    1.67 +         break;
    1.68 +
    1.69 +      case PNG_CRC_WARN_USE:                              /* Warn/use data */
    1.70 +         png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
    1.71 +         png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE;
    1.72 +         break;
    1.73 +
    1.74 +      case PNG_CRC_QUIET_USE:                            /* Quiet/use data */
    1.75 +         png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
    1.76 +         png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE |
    1.77 +                           PNG_FLAG_CRC_ANCILLARY_NOWARN;
    1.78 +         break;
    1.79 +
    1.80 +      case PNG_CRC_ERROR_QUIT:                               /* Error/quit */
    1.81 +         png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
    1.82 +         png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN;
    1.83 +         break;
    1.84 +
    1.85 +      case PNG_CRC_WARN_DISCARD:                      /* Warn/discard data */
    1.86 +
    1.87 +      case PNG_CRC_DEFAULT:
    1.88 +      default:
    1.89 +         png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
    1.90 +         break;
    1.91 +   }
    1.92 +}
    1.93 +
    1.94 +#ifdef PNG_READ_TRANSFORMS_SUPPORTED
    1.95 +/* Is it OK to set a transformation now?  Only if png_start_read_image or
    1.96 + * png_read_update_info have not been called.  It is not necessary for the IHDR
    1.97 + * to have been read in all cases, the parameter allows for this check too.
    1.98 + */
    1.99 +static int
   1.100 +png_rtran_ok(png_structrp png_ptr, int need_IHDR)
   1.101 +{
   1.102 +   if (png_ptr != NULL)
   1.103 +   {
   1.104 +      if (png_ptr->flags & PNG_FLAG_ROW_INIT)
   1.105 +         png_app_error(png_ptr,
   1.106 +            "invalid after png_start_read_image or png_read_update_info");
   1.107 +
   1.108 +      else if (need_IHDR && (png_ptr->mode & PNG_HAVE_IHDR) == 0)
   1.109 +         png_app_error(png_ptr, "invalid before the PNG header has been read");
   1.110 +
   1.111 +      else
   1.112 +      {
   1.113 +         /* Turn on failure to initialize correctly for all transforms. */
   1.114 +         png_ptr->flags |= PNG_FLAG_DETECT_UNINITIALIZED;
   1.115 +
   1.116 +         return 1; /* Ok */
   1.117 +      }
   1.118 +   }
   1.119 +
   1.120 +   return 0; /* no png_error possible! */
   1.121 +}
   1.122 +#endif
   1.123 +
   1.124 +#ifdef PNG_READ_BACKGROUND_SUPPORTED
   1.125 +/* Handle alpha and tRNS via a background color */
   1.126 +void PNGFAPI
   1.127 +png_set_background_fixed(png_structrp png_ptr,
   1.128 +    png_const_color_16p background_color, int background_gamma_code,
   1.129 +    int need_expand, png_fixed_point background_gamma)
   1.130 +{
   1.131 +   png_debug(1, "in png_set_background_fixed");
   1.132 +
   1.133 +   if (!png_rtran_ok(png_ptr, 0) || background_color == NULL)
   1.134 +      return;
   1.135 +
   1.136 +   if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN)
   1.137 +   {
   1.138 +      png_warning(png_ptr, "Application must supply a known background gamma");
   1.139 +      return;
   1.140 +   }
   1.141 +
   1.142 +   png_ptr->transformations |= PNG_COMPOSE | PNG_STRIP_ALPHA;
   1.143 +   png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
   1.144 +   png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
   1.145 +
   1.146 +   png_ptr->background = *background_color;
   1.147 +   png_ptr->background_gamma = background_gamma;
   1.148 +   png_ptr->background_gamma_type = (png_byte)(background_gamma_code);
   1.149 +   if (need_expand)
   1.150 +      png_ptr->transformations |= PNG_BACKGROUND_EXPAND;
   1.151 +   else
   1.152 +      png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND;
   1.153 +}
   1.154 +
   1.155 +#  ifdef PNG_FLOATING_POINT_SUPPORTED
   1.156 +void PNGAPI
   1.157 +png_set_background(png_structrp png_ptr,
   1.158 +    png_const_color_16p background_color, int background_gamma_code,
   1.159 +    int need_expand, double background_gamma)
   1.160 +{
   1.161 +   png_set_background_fixed(png_ptr, background_color, background_gamma_code,
   1.162 +      need_expand, png_fixed(png_ptr, background_gamma, "png_set_background"));
   1.163 +}
   1.164 +#  endif  /* FLOATING_POINT */
   1.165 +#endif /* READ_BACKGROUND */
   1.166 +
   1.167 +/* Scale 16-bit depth files to 8-bit depth.  If both of these are set then the
   1.168 + * one that pngrtran does first (scale) happens.  This is necessary to allow the
   1.169 + * TRANSFORM and API behavior to be somewhat consistent, and it's simpler.
   1.170 + */
   1.171 +#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
   1.172 +void PNGAPI
   1.173 +png_set_scale_16(png_structrp png_ptr)
   1.174 +{
   1.175 +   png_debug(1, "in png_set_scale_16");
   1.176 +
   1.177 +   if (!png_rtran_ok(png_ptr, 0))
   1.178 +      return;
   1.179 +
   1.180 +   png_ptr->transformations |= PNG_SCALE_16_TO_8;
   1.181 +}
   1.182 +#endif
   1.183 +
   1.184 +#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
   1.185 +/* Chop 16-bit depth files to 8-bit depth */
   1.186 +void PNGAPI
   1.187 +png_set_strip_16(png_structrp png_ptr)
   1.188 +{
   1.189 +   png_debug(1, "in png_set_strip_16");
   1.190 +
   1.191 +   if (!png_rtran_ok(png_ptr, 0))
   1.192 +      return;
   1.193 +
   1.194 +   png_ptr->transformations |= PNG_16_TO_8;
   1.195 +}
   1.196 +#endif
   1.197 +
   1.198 +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
   1.199 +void PNGAPI
   1.200 +png_set_strip_alpha(png_structrp png_ptr)
   1.201 +{
   1.202 +   png_debug(1, "in png_set_strip_alpha");
   1.203 +
   1.204 +   if (!png_rtran_ok(png_ptr, 0))
   1.205 +      return;
   1.206 +
   1.207 +   png_ptr->transformations |= PNG_STRIP_ALPHA;
   1.208 +}
   1.209 +#endif
   1.210 +
   1.211 +#if defined(PNG_READ_ALPHA_MODE_SUPPORTED) || defined(PNG_READ_GAMMA_SUPPORTED)
   1.212 +static png_fixed_point
   1.213 +translate_gamma_flags(png_structrp png_ptr, png_fixed_point output_gamma,
   1.214 +   int is_screen)
   1.215 +{
   1.216 +   /* Check for flag values.  The main reason for having the old Mac value as a
   1.217 +    * flag is that it is pretty near impossible to work out what the correct
   1.218 +    * value is from Apple documentation - a working Mac system is needed to
   1.219 +    * discover the value!
   1.220 +    */
   1.221 +   if (output_gamma == PNG_DEFAULT_sRGB ||
   1.222 +      output_gamma == PNG_FP_1 / PNG_DEFAULT_sRGB)
   1.223 +   {
   1.224 +      /* If there is no sRGB support this just sets the gamma to the standard
   1.225 +       * sRGB value.  (This is a side effect of using this function!)
   1.226 +       */
   1.227 +#     ifdef PNG_READ_sRGB_SUPPORTED
   1.228 +         png_ptr->flags |= PNG_FLAG_ASSUME_sRGB;
   1.229 +#     else
   1.230 +         PNG_UNUSED(png_ptr)
   1.231 +#     endif
   1.232 +      if (is_screen)
   1.233 +         output_gamma = PNG_GAMMA_sRGB;
   1.234 +      else
   1.235 +         output_gamma = PNG_GAMMA_sRGB_INVERSE;
   1.236 +   }
   1.237 +
   1.238 +   else if (output_gamma == PNG_GAMMA_MAC_18 ||
   1.239 +      output_gamma == PNG_FP_1 / PNG_GAMMA_MAC_18)
   1.240 +   {
   1.241 +      if (is_screen)
   1.242 +         output_gamma = PNG_GAMMA_MAC_OLD;
   1.243 +      else
   1.244 +         output_gamma = PNG_GAMMA_MAC_INVERSE;
   1.245 +   }
   1.246 +
   1.247 +   return output_gamma;
   1.248 +}
   1.249 +
   1.250 +#  ifdef PNG_FLOATING_POINT_SUPPORTED
   1.251 +static png_fixed_point
   1.252 +convert_gamma_value(png_structrp png_ptr, double output_gamma)
   1.253 +{
   1.254 +   /* The following silently ignores cases where fixed point (times 100,000)
   1.255 +    * gamma values are passed to the floating point API.  This is safe and it
   1.256 +    * means the fixed point constants work just fine with the floating point
   1.257 +    * API.  The alternative would just lead to undetected errors and spurious
   1.258 +    * bug reports.  Negative values fail inside the _fixed API unless they
   1.259 +    * correspond to the flag values.
   1.260 +    */
   1.261 +   if (output_gamma > 0 && output_gamma < 128)
   1.262 +      output_gamma *= PNG_FP_1;
   1.263 +
   1.264 +   /* This preserves -1 and -2 exactly: */
   1.265 +   output_gamma = floor(output_gamma + .5);
   1.266 +
   1.267 +   if (output_gamma > PNG_FP_MAX || output_gamma < PNG_FP_MIN)
   1.268 +      png_fixed_error(png_ptr, "gamma value");
   1.269 +
   1.270 +   return (png_fixed_point)output_gamma;
   1.271 +}
   1.272 +#  endif
   1.273 +#endif /* READ_ALPHA_MODE || READ_GAMMA */
   1.274 +
   1.275 +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
   1.276 +void PNGFAPI
   1.277 +png_set_alpha_mode_fixed(png_structrp png_ptr, int mode,
   1.278 +   png_fixed_point output_gamma)
   1.279 +{
   1.280 +   int compose = 0;
   1.281 +   png_fixed_point file_gamma;
   1.282 +
   1.283 +   png_debug(1, "in png_set_alpha_mode");
   1.284 +
   1.285 +   if (!png_rtran_ok(png_ptr, 0))
   1.286 +      return;
   1.287 +
   1.288 +   output_gamma = translate_gamma_flags(png_ptr, output_gamma, 1/*screen*/);
   1.289 +
   1.290 +   /* Validate the value to ensure it is in a reasonable range. The value
   1.291 +    * is expected to be 1 or greater, but this range test allows for some
   1.292 +    * viewing correction values.  The intent is to weed out users of this API
   1.293 +    * who use the inverse of the gamma value accidentally!  Since some of these
   1.294 +    * values are reasonable this may have to be changed.
   1.295 +    */
   1.296 +   if (output_gamma < 70000 || output_gamma > 300000)
   1.297 +      png_error(png_ptr, "output gamma out of expected range");
   1.298 +
   1.299 +   /* The default file gamma is the inverse of the output gamma; the output
   1.300 +    * gamma may be changed below so get the file value first:
   1.301 +    */
   1.302 +   file_gamma = png_reciprocal(output_gamma);
   1.303 +
   1.304 +   /* There are really 8 possibilities here, composed of any combination
   1.305 +    * of:
   1.306 +    *
   1.307 +    *    premultiply the color channels
   1.308 +    *    do not encode non-opaque pixels
   1.309 +    *    encode the alpha as well as the color channels
   1.310 +    *
   1.311 +    * The differences disappear if the input/output ('screen') gamma is 1.0,
   1.312 +    * because then the encoding is a no-op and there is only the choice of
   1.313 +    * premultiplying the color channels or not.
   1.314 +    *
   1.315 +    * png_set_alpha_mode and png_set_background interact because both use
   1.316 +    * png_compose to do the work.  Calling both is only useful when
   1.317 +    * png_set_alpha_mode is used to set the default mode - PNG_ALPHA_PNG - along
   1.318 +    * with a default gamma value.  Otherwise PNG_COMPOSE must not be set.
   1.319 +    */
   1.320 +   switch (mode)
   1.321 +   {
   1.322 +      case PNG_ALPHA_PNG:        /* default: png standard */
   1.323 +         /* No compose, but it may be set by png_set_background! */
   1.324 +         png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
   1.325 +         png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
   1.326 +         break;
   1.327 +
   1.328 +      case PNG_ALPHA_ASSOCIATED: /* color channels premultiplied */
   1.329 +         compose = 1;
   1.330 +         png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
   1.331 +         png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
   1.332 +         /* The output is linear: */
   1.333 +         output_gamma = PNG_FP_1;
   1.334 +         break;
   1.335 +
   1.336 +      case PNG_ALPHA_OPTIMIZED:  /* associated, non-opaque pixels linear */
   1.337 +         compose = 1;
   1.338 +         png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
   1.339 +         png_ptr->flags |= PNG_FLAG_OPTIMIZE_ALPHA;
   1.340 +         /* output_gamma records the encoding of opaque pixels! */
   1.341 +         break;
   1.342 +
   1.343 +      case PNG_ALPHA_BROKEN:     /* associated, non-linear, alpha encoded */
   1.344 +         compose = 1;
   1.345 +         png_ptr->transformations |= PNG_ENCODE_ALPHA;
   1.346 +         png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
   1.347 +         break;
   1.348 +
   1.349 +      default:
   1.350 +         png_error(png_ptr, "invalid alpha mode");
   1.351 +   }
   1.352 +
   1.353 +   /* Only set the default gamma if the file gamma has not been set (this has
   1.354 +    * the side effect that the gamma in a second call to png_set_alpha_mode will
   1.355 +    * be ignored.)
   1.356 +    */
   1.357 +   if (png_ptr->colorspace.gamma == 0)
   1.358 +   {
   1.359 +      png_ptr->colorspace.gamma = file_gamma;
   1.360 +      png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;
   1.361 +   }
   1.362 +
   1.363 +   /* But always set the output gamma: */
   1.364 +   png_ptr->screen_gamma = output_gamma;
   1.365 +
   1.366 +   /* Finally, if pre-multiplying, set the background fields to achieve the
   1.367 +    * desired result.
   1.368 +    */
   1.369 +   if (compose)
   1.370 +   {
   1.371 +      /* And obtain alpha pre-multiplication by composing on black: */
   1.372 +      memset(&png_ptr->background, 0, (sizeof png_ptr->background));
   1.373 +      png_ptr->background_gamma = png_ptr->colorspace.gamma; /* just in case */
   1.374 +      png_ptr->background_gamma_type = PNG_BACKGROUND_GAMMA_FILE;
   1.375 +      png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND;
   1.376 +
   1.377 +      if (png_ptr->transformations & PNG_COMPOSE)
   1.378 +         png_error(png_ptr,
   1.379 +            "conflicting calls to set alpha mode and background");
   1.380 +
   1.381 +      png_ptr->transformations |= PNG_COMPOSE;
   1.382 +   }
   1.383 +}
   1.384 +
   1.385 +#  ifdef PNG_FLOATING_POINT_SUPPORTED
   1.386 +void PNGAPI
   1.387 +png_set_alpha_mode(png_structrp png_ptr, int mode, double output_gamma)
   1.388 +{
   1.389 +   png_set_alpha_mode_fixed(png_ptr, mode, convert_gamma_value(png_ptr,
   1.390 +      output_gamma));
   1.391 +}
   1.392 +#  endif
   1.393 +#endif
   1.394 +
   1.395 +#ifdef PNG_READ_QUANTIZE_SUPPORTED
   1.396 +/* Dither file to 8-bit.  Supply a palette, the current number
   1.397 + * of elements in the palette, the maximum number of elements
   1.398 + * allowed, and a histogram if possible.  If the current number
   1.399 + * of colors is greater then the maximum number, the palette will be
   1.400 + * modified to fit in the maximum number.  "full_quantize" indicates
   1.401 + * whether we need a quantizing cube set up for RGB images, or if we
   1.402 + * simply are reducing the number of colors in a paletted image.
   1.403 + */
   1.404 +
   1.405 +typedef struct png_dsort_struct
   1.406 +{
   1.407 +   struct png_dsort_struct * next;
   1.408 +   png_byte left;
   1.409 +   png_byte right;
   1.410 +} png_dsort;
   1.411 +typedef png_dsort *   png_dsortp;
   1.412 +typedef png_dsort * * png_dsortpp;
   1.413 +
   1.414 +void PNGAPI
   1.415 +png_set_quantize(png_structrp png_ptr, png_colorp palette,
   1.416 +    int num_palette, int maximum_colors, png_const_uint_16p histogram,
   1.417 +    int full_quantize)
   1.418 +{
   1.419 +   png_debug(1, "in png_set_quantize");
   1.420 +
   1.421 +   if (!png_rtran_ok(png_ptr, 0))
   1.422 +      return;
   1.423 +
   1.424 +   png_ptr->transformations |= PNG_QUANTIZE;
   1.425 +
   1.426 +   if (!full_quantize)
   1.427 +   {
   1.428 +      int i;
   1.429 +
   1.430 +      png_ptr->quantize_index = (png_bytep)png_malloc(png_ptr,
   1.431 +          (png_uint_32)(num_palette * (sizeof (png_byte))));
   1.432 +      for (i = 0; i < num_palette; i++)
   1.433 +         png_ptr->quantize_index[i] = (png_byte)i;
   1.434 +   }
   1.435 +
   1.436 +   if (num_palette > maximum_colors)
   1.437 +   {
   1.438 +      if (histogram != NULL)
   1.439 +      {
   1.440 +         /* This is easy enough, just throw out the least used colors.
   1.441 +          * Perhaps not the best solution, but good enough.
   1.442 +          */
   1.443 +
   1.444 +         int i;
   1.445 +
   1.446 +         /* Initialize an array to sort colors */
   1.447 +         png_ptr->quantize_sort = (png_bytep)png_malloc(png_ptr,
   1.448 +             (png_uint_32)(num_palette * (sizeof (png_byte))));
   1.449 +
   1.450 +         /* Initialize the quantize_sort array */
   1.451 +         for (i = 0; i < num_palette; i++)
   1.452 +            png_ptr->quantize_sort[i] = (png_byte)i;
   1.453 +
   1.454 +         /* Find the least used palette entries by starting a
   1.455 +          * bubble sort, and running it until we have sorted
   1.456 +          * out enough colors.  Note that we don't care about
   1.457 +          * sorting all the colors, just finding which are
   1.458 +          * least used.
   1.459 +          */
   1.460 +
   1.461 +         for (i = num_palette - 1; i >= maximum_colors; i--)
   1.462 +         {
   1.463 +            int done; /* To stop early if the list is pre-sorted */
   1.464 +            int j;
   1.465 +
   1.466 +            done = 1;
   1.467 +            for (j = 0; j < i; j++)
   1.468 +            {
   1.469 +               if (histogram[png_ptr->quantize_sort[j]]
   1.470 +                   < histogram[png_ptr->quantize_sort[j + 1]])
   1.471 +               {
   1.472 +                  png_byte t;
   1.473 +
   1.474 +                  t = png_ptr->quantize_sort[j];
   1.475 +                  png_ptr->quantize_sort[j] = png_ptr->quantize_sort[j + 1];
   1.476 +                  png_ptr->quantize_sort[j + 1] = t;
   1.477 +                  done = 0;
   1.478 +               }
   1.479 +            }
   1.480 +
   1.481 +            if (done)
   1.482 +               break;
   1.483 +         }
   1.484 +
   1.485 +         /* Swap the palette around, and set up a table, if necessary */
   1.486 +         if (full_quantize)
   1.487 +         {
   1.488 +            int j = num_palette;
   1.489 +
   1.490 +            /* Put all the useful colors within the max, but don't
   1.491 +             * move the others.
   1.492 +             */
   1.493 +            for (i = 0; i < maximum_colors; i++)
   1.494 +            {
   1.495 +               if ((int)png_ptr->quantize_sort[i] >= maximum_colors)
   1.496 +               {
   1.497 +                  do
   1.498 +                     j--;
   1.499 +                  while ((int)png_ptr->quantize_sort[j] >= maximum_colors);
   1.500 +
   1.501 +                  palette[i] = palette[j];
   1.502 +               }
   1.503 +            }
   1.504 +         }
   1.505 +         else
   1.506 +         {
   1.507 +            int j = num_palette;
   1.508 +
   1.509 +            /* Move all the used colors inside the max limit, and
   1.510 +             * develop a translation table.
   1.511 +             */
   1.512 +            for (i = 0; i < maximum_colors; i++)
   1.513 +            {
   1.514 +               /* Only move the colors we need to */
   1.515 +               if ((int)png_ptr->quantize_sort[i] >= maximum_colors)
   1.516 +               {
   1.517 +                  png_color tmp_color;
   1.518 +
   1.519 +                  do
   1.520 +                     j--;
   1.521 +                  while ((int)png_ptr->quantize_sort[j] >= maximum_colors);
   1.522 +
   1.523 +                  tmp_color = palette[j];
   1.524 +                  palette[j] = palette[i];
   1.525 +                  palette[i] = tmp_color;
   1.526 +                  /* Indicate where the color went */
   1.527 +                  png_ptr->quantize_index[j] = (png_byte)i;
   1.528 +                  png_ptr->quantize_index[i] = (png_byte)j;
   1.529 +               }
   1.530 +            }
   1.531 +
   1.532 +            /* Find closest color for those colors we are not using */
   1.533 +            for (i = 0; i < num_palette; i++)
   1.534 +            {
   1.535 +               if ((int)png_ptr->quantize_index[i] >= maximum_colors)
   1.536 +               {
   1.537 +                  int min_d, k, min_k, d_index;
   1.538 +
   1.539 +                  /* Find the closest color to one we threw out */
   1.540 +                  d_index = png_ptr->quantize_index[i];
   1.541 +                  min_d = PNG_COLOR_DIST(palette[d_index], palette[0]);
   1.542 +                  for (k = 1, min_k = 0; k < maximum_colors; k++)
   1.543 +                  {
   1.544 +                     int d;
   1.545 +
   1.546 +                     d = PNG_COLOR_DIST(palette[d_index], palette[k]);
   1.547 +
   1.548 +                     if (d < min_d)
   1.549 +                     {
   1.550 +                        min_d = d;
   1.551 +                        min_k = k;
   1.552 +                     }
   1.553 +                  }
   1.554 +                  /* Point to closest color */
   1.555 +                  png_ptr->quantize_index[i] = (png_byte)min_k;
   1.556 +               }
   1.557 +            }
   1.558 +         }
   1.559 +         png_free(png_ptr, png_ptr->quantize_sort);
   1.560 +         png_ptr->quantize_sort = NULL;
   1.561 +      }
   1.562 +      else
   1.563 +      {
   1.564 +         /* This is much harder to do simply (and quickly).  Perhaps
   1.565 +          * we need to go through a median cut routine, but those
   1.566 +          * don't always behave themselves with only a few colors
   1.567 +          * as input.  So we will just find the closest two colors,
   1.568 +          * and throw out one of them (chosen somewhat randomly).
   1.569 +          * [We don't understand this at all, so if someone wants to
   1.570 +          *  work on improving it, be our guest - AED, GRP]
   1.571 +          */
   1.572 +         int i;
   1.573 +         int max_d;
   1.574 +         int num_new_palette;
   1.575 +         png_dsortp t;
   1.576 +         png_dsortpp hash;
   1.577 +
   1.578 +         t = NULL;
   1.579 +
   1.580 +         /* Initialize palette index arrays */
   1.581 +         png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr,
   1.582 +             (png_uint_32)(num_palette * (sizeof (png_byte))));
   1.583 +         png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr,
   1.584 +             (png_uint_32)(num_palette * (sizeof (png_byte))));
   1.585 +
   1.586 +         /* Initialize the sort array */
   1.587 +         for (i = 0; i < num_palette; i++)
   1.588 +         {
   1.589 +            png_ptr->index_to_palette[i] = (png_byte)i;
   1.590 +            png_ptr->palette_to_index[i] = (png_byte)i;
   1.591 +         }
   1.592 +
   1.593 +         hash = (png_dsortpp)png_calloc(png_ptr, (png_uint_32)(769 *
   1.594 +             (sizeof (png_dsortp))));
   1.595 +
   1.596 +         num_new_palette = num_palette;
   1.597 +
   1.598 +         /* Initial wild guess at how far apart the farthest pixel
   1.599 +          * pair we will be eliminating will be.  Larger
   1.600 +          * numbers mean more areas will be allocated, Smaller
   1.601 +          * numbers run the risk of not saving enough data, and
   1.602 +          * having to do this all over again.
   1.603 +          *
   1.604 +          * I have not done extensive checking on this number.
   1.605 +          */
   1.606 +         max_d = 96;
   1.607 +
   1.608 +         while (num_new_palette > maximum_colors)
   1.609 +         {
   1.610 +            for (i = 0; i < num_new_palette - 1; i++)
   1.611 +            {
   1.612 +               int j;
   1.613 +
   1.614 +               for (j = i + 1; j < num_new_palette; j++)
   1.615 +               {
   1.616 +                  int d;
   1.617 +
   1.618 +                  d = PNG_COLOR_DIST(palette[i], palette[j]);
   1.619 +
   1.620 +                  if (d <= max_d)
   1.621 +                  {
   1.622 +
   1.623 +                     t = (png_dsortp)png_malloc_warn(png_ptr,
   1.624 +                         (png_uint_32)(sizeof (png_dsort)));
   1.625 +
   1.626 +                     if (t == NULL)
   1.627 +                         break;
   1.628 +
   1.629 +                     t->next = hash[d];
   1.630 +                     t->left = (png_byte)i;
   1.631 +                     t->right = (png_byte)j;
   1.632 +                     hash[d] = t;
   1.633 +                  }
   1.634 +               }
   1.635 +               if (t == NULL)
   1.636 +                  break;
   1.637 +            }
   1.638 +
   1.639 +            if (t != NULL)
   1.640 +            for (i = 0; i <= max_d; i++)
   1.641 +            {
   1.642 +               if (hash[i] != NULL)
   1.643 +               {
   1.644 +                  png_dsortp p;
   1.645 +
   1.646 +                  for (p = hash[i]; p; p = p->next)
   1.647 +                  {
   1.648 +                     if ((int)png_ptr->index_to_palette[p->left]
   1.649 +                         < num_new_palette &&
   1.650 +                         (int)png_ptr->index_to_palette[p->right]
   1.651 +                         < num_new_palette)
   1.652 +                     {
   1.653 +                        int j, next_j;
   1.654 +
   1.655 +                        if (num_new_palette & 0x01)
   1.656 +                        {
   1.657 +                           j = p->left;
   1.658 +                           next_j = p->right;
   1.659 +                        }
   1.660 +                        else
   1.661 +                        {
   1.662 +                           j = p->right;
   1.663 +                           next_j = p->left;
   1.664 +                        }
   1.665 +
   1.666 +                        num_new_palette--;
   1.667 +                        palette[png_ptr->index_to_palette[j]]
   1.668 +                            = palette[num_new_palette];
   1.669 +                        if (!full_quantize)
   1.670 +                        {
   1.671 +                           int k;
   1.672 +
   1.673 +                           for (k = 0; k < num_palette; k++)
   1.674 +                           {
   1.675 +                              if (png_ptr->quantize_index[k] ==
   1.676 +                                  png_ptr->index_to_palette[j])
   1.677 +                                 png_ptr->quantize_index[k] =
   1.678 +                                     png_ptr->index_to_palette[next_j];
   1.679 +
   1.680 +                              if ((int)png_ptr->quantize_index[k] ==
   1.681 +                                  num_new_palette)
   1.682 +                                 png_ptr->quantize_index[k] =
   1.683 +                                     png_ptr->index_to_palette[j];
   1.684 +                           }
   1.685 +                        }
   1.686 +
   1.687 +                        png_ptr->index_to_palette[png_ptr->palette_to_index
   1.688 +                            [num_new_palette]] = png_ptr->index_to_palette[j];
   1.689 +
   1.690 +                        png_ptr->palette_to_index[png_ptr->index_to_palette[j]]
   1.691 +                            = png_ptr->palette_to_index[num_new_palette];
   1.692 +
   1.693 +                        png_ptr->index_to_palette[j] =
   1.694 +                            (png_byte)num_new_palette;
   1.695 +
   1.696 +                        png_ptr->palette_to_index[num_new_palette] =
   1.697 +                            (png_byte)j;
   1.698 +                     }
   1.699 +                     if (num_new_palette <= maximum_colors)
   1.700 +                        break;
   1.701 +                  }
   1.702 +                  if (num_new_palette <= maximum_colors)
   1.703 +                     break;
   1.704 +               }
   1.705 +            }
   1.706 +
   1.707 +            for (i = 0; i < 769; i++)
   1.708 +            {
   1.709 +               if (hash[i] != NULL)
   1.710 +               {
   1.711 +                  png_dsortp p = hash[i];
   1.712 +                  while (p)
   1.713 +                  {
   1.714 +                     t = p->next;
   1.715 +                     png_free(png_ptr, p);
   1.716 +                     p = t;
   1.717 +                  }
   1.718 +               }
   1.719 +               hash[i] = 0;
   1.720 +            }
   1.721 +            max_d += 96;
   1.722 +         }
   1.723 +         png_free(png_ptr, hash);
   1.724 +         png_free(png_ptr, png_ptr->palette_to_index);
   1.725 +         png_free(png_ptr, png_ptr->index_to_palette);
   1.726 +         png_ptr->palette_to_index = NULL;
   1.727 +         png_ptr->index_to_palette = NULL;
   1.728 +      }
   1.729 +      num_palette = maximum_colors;
   1.730 +   }
   1.731 +   if (png_ptr->palette == NULL)
   1.732 +   {
   1.733 +      png_ptr->palette = palette;
   1.734 +   }
   1.735 +   png_ptr->num_palette = (png_uint_16)num_palette;
   1.736 +
   1.737 +   if (full_quantize)
   1.738 +   {
   1.739 +      int i;
   1.740 +      png_bytep distance;
   1.741 +      int total_bits = PNG_QUANTIZE_RED_BITS + PNG_QUANTIZE_GREEN_BITS +
   1.742 +          PNG_QUANTIZE_BLUE_BITS;
   1.743 +      int num_red = (1 << PNG_QUANTIZE_RED_BITS);
   1.744 +      int num_green = (1 << PNG_QUANTIZE_GREEN_BITS);
   1.745 +      int num_blue = (1 << PNG_QUANTIZE_BLUE_BITS);
   1.746 +      png_size_t num_entries = ((png_size_t)1 << total_bits);
   1.747 +
   1.748 +      png_ptr->palette_lookup = (png_bytep)png_calloc(png_ptr,
   1.749 +          (png_uint_32)(num_entries * (sizeof (png_byte))));
   1.750 +
   1.751 +      distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries *
   1.752 +          (sizeof (png_byte))));
   1.753 +
   1.754 +      memset(distance, 0xff, num_entries * (sizeof (png_byte)));
   1.755 +
   1.756 +      for (i = 0; i < num_palette; i++)
   1.757 +      {
   1.758 +         int ir, ig, ib;
   1.759 +         int r = (palette[i].red >> (8 - PNG_QUANTIZE_RED_BITS));
   1.760 +         int g = (palette[i].green >> (8 - PNG_QUANTIZE_GREEN_BITS));
   1.761 +         int b = (palette[i].blue >> (8 - PNG_QUANTIZE_BLUE_BITS));
   1.762 +
   1.763 +         for (ir = 0; ir < num_red; ir++)
   1.764 +         {
   1.765 +            /* int dr = abs(ir - r); */
   1.766 +            int dr = ((ir > r) ? ir - r : r - ir);
   1.767 +            int index_r = (ir << (PNG_QUANTIZE_BLUE_BITS +
   1.768 +                PNG_QUANTIZE_GREEN_BITS));
   1.769 +
   1.770 +            for (ig = 0; ig < num_green; ig++)
   1.771 +            {
   1.772 +               /* int dg = abs(ig - g); */
   1.773 +               int dg = ((ig > g) ? ig - g : g - ig);
   1.774 +               int dt = dr + dg;
   1.775 +               int dm = ((dr > dg) ? dr : dg);
   1.776 +               int index_g = index_r | (ig << PNG_QUANTIZE_BLUE_BITS);
   1.777 +
   1.778 +               for (ib = 0; ib < num_blue; ib++)
   1.779 +               {
   1.780 +                  int d_index = index_g | ib;
   1.781 +                  /* int db = abs(ib - b); */
   1.782 +                  int db = ((ib > b) ? ib - b : b - ib);
   1.783 +                  int dmax = ((dm > db) ? dm : db);
   1.784 +                  int d = dmax + dt + db;
   1.785 +
   1.786 +                  if (d < (int)distance[d_index])
   1.787 +                  {
   1.788 +                     distance[d_index] = (png_byte)d;
   1.789 +                     png_ptr->palette_lookup[d_index] = (png_byte)i;
   1.790 +                  }
   1.791 +               }
   1.792 +            }
   1.793 +         }
   1.794 +      }
   1.795 +
   1.796 +      png_free(png_ptr, distance);
   1.797 +   }
   1.798 +}
   1.799 +#endif /* PNG_READ_QUANTIZE_SUPPORTED */
   1.800 +
   1.801 +#ifdef PNG_READ_GAMMA_SUPPORTED
   1.802 +void PNGFAPI
   1.803 +png_set_gamma_fixed(png_structrp png_ptr, png_fixed_point scrn_gamma,
   1.804 +   png_fixed_point file_gamma)
   1.805 +{
   1.806 +   png_debug(1, "in png_set_gamma_fixed");
   1.807 +
   1.808 +   if (!png_rtran_ok(png_ptr, 0))
   1.809 +      return;
   1.810 +
   1.811 +   /* New in libpng-1.5.4 - reserve particular negative values as flags. */
   1.812 +   scrn_gamma = translate_gamma_flags(png_ptr, scrn_gamma, 1/*screen*/);
   1.813 +   file_gamma = translate_gamma_flags(png_ptr, file_gamma, 0/*file*/);
   1.814 +
   1.815 +   /* Checking the gamma values for being >0 was added in 1.5.4 along with the
   1.816 +    * premultiplied alpha support; this actually hides an undocumented feature
   1.817 +    * of the previous implementation which allowed gamma processing to be
   1.818 +    * disabled in background handling.  There is no evidence (so far) that this
   1.819 +    * was being used; however, png_set_background itself accepted and must still
   1.820 +    * accept '0' for the gamma value it takes, because it isn't always used.
   1.821 +    *
   1.822 +    * Since this is an API change (albeit a very minor one that removes an
   1.823 +    * undocumented API feature) the following checks were only enabled in
   1.824 +    * libpng-1.6.0.
   1.825 +    */
   1.826 +   if (file_gamma <= 0)
   1.827 +      png_error(png_ptr, "invalid file gamma in png_set_gamma");
   1.828 +
   1.829 +   if (scrn_gamma <= 0)
   1.830 +      png_error(png_ptr, "invalid screen gamma in png_set_gamma");
   1.831 +
   1.832 +   /* Set the gamma values unconditionally - this overrides the value in the PNG
   1.833 +    * file if a gAMA chunk was present.  png_set_alpha_mode provides a
   1.834 +    * different, easier, way to default the file gamma.
   1.835 +    */
   1.836 +   png_ptr->colorspace.gamma = file_gamma;
   1.837 +   png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;
   1.838 +   png_ptr->screen_gamma = scrn_gamma;
   1.839 +}
   1.840 +
   1.841 +#  ifdef PNG_FLOATING_POINT_SUPPORTED
   1.842 +void PNGAPI
   1.843 +png_set_gamma(png_structrp png_ptr, double scrn_gamma, double file_gamma)
   1.844 +{
   1.845 +   png_set_gamma_fixed(png_ptr, convert_gamma_value(png_ptr, scrn_gamma),
   1.846 +      convert_gamma_value(png_ptr, file_gamma));
   1.847 +}
   1.848 +#  endif /* FLOATING_POINT_SUPPORTED */
   1.849 +#endif /* READ_GAMMA */
   1.850 +
   1.851 +#ifdef PNG_READ_EXPAND_SUPPORTED
   1.852 +/* Expand paletted images to RGB, expand grayscale images of
   1.853 + * less than 8-bit depth to 8-bit depth, and expand tRNS chunks
   1.854 + * to alpha channels.
   1.855 + */
   1.856 +void PNGAPI
   1.857 +png_set_expand(png_structrp png_ptr)
   1.858 +{
   1.859 +   png_debug(1, "in png_set_expand");
   1.860 +
   1.861 +   if (!png_rtran_ok(png_ptr, 0))
   1.862 +      return;
   1.863 +
   1.864 +   png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
   1.865 +}
   1.866 +
   1.867 +/* GRR 19990627:  the following three functions currently are identical
   1.868 + *  to png_set_expand().  However, it is entirely reasonable that someone
   1.869 + *  might wish to expand an indexed image to RGB but *not* expand a single,
   1.870 + *  fully transparent palette entry to a full alpha channel--perhaps instead
   1.871 + *  convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace
   1.872 + *  the transparent color with a particular RGB value, or drop tRNS entirely.
   1.873 + *  IOW, a future version of the library may make the transformations flag
   1.874 + *  a bit more fine-grained, with separate bits for each of these three
   1.875 + *  functions.
   1.876 + *
   1.877 + *  More to the point, these functions make it obvious what libpng will be
   1.878 + *  doing, whereas "expand" can (and does) mean any number of things.
   1.879 + *
   1.880 + *  GRP 20060307: In libpng-1.2.9, png_set_gray_1_2_4_to_8() was modified
   1.881 + *  to expand only the sample depth but not to expand the tRNS to alpha
   1.882 + *  and its name was changed to png_set_expand_gray_1_2_4_to_8().
   1.883 + */
   1.884 +
   1.885 +/* Expand paletted images to RGB. */
   1.886 +void PNGAPI
   1.887 +png_set_palette_to_rgb(png_structrp png_ptr)
   1.888 +{
   1.889 +   png_debug(1, "in png_set_palette_to_rgb");
   1.890 +
   1.891 +   if (!png_rtran_ok(png_ptr, 0))
   1.892 +      return;
   1.893 +
   1.894 +   png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
   1.895 +}
   1.896 +
   1.897 +/* Expand grayscale images of less than 8-bit depth to 8 bits. */
   1.898 +void PNGAPI
   1.899 +png_set_expand_gray_1_2_4_to_8(png_structrp png_ptr)
   1.900 +{
   1.901 +   png_debug(1, "in png_set_expand_gray_1_2_4_to_8");
   1.902 +
   1.903 +   if (!png_rtran_ok(png_ptr, 0))
   1.904 +      return;
   1.905 +
   1.906 +   png_ptr->transformations |= PNG_EXPAND;
   1.907 +}
   1.908 +
   1.909 +/* Expand tRNS chunks to alpha channels. */
   1.910 +void PNGAPI
   1.911 +png_set_tRNS_to_alpha(png_structrp png_ptr)
   1.912 +{
   1.913 +   png_debug(1, "in png_set_tRNS_to_alpha");
   1.914 +
   1.915 +   if (!png_rtran_ok(png_ptr, 0))
   1.916 +      return;
   1.917 +
   1.918 +   png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
   1.919 +}
   1.920 +#endif /* defined(PNG_READ_EXPAND_SUPPORTED) */
   1.921 +
   1.922 +#ifdef PNG_READ_EXPAND_16_SUPPORTED
   1.923 +/* Expand to 16-bit channels, expand the tRNS chunk too (because otherwise
   1.924 + * it may not work correctly.)
   1.925 + */
   1.926 +void PNGAPI
   1.927 +png_set_expand_16(png_structrp png_ptr)
   1.928 +{
   1.929 +   png_debug(1, "in png_set_expand_16");
   1.930 +
   1.931 +   if (!png_rtran_ok(png_ptr, 0))
   1.932 +      return;
   1.933 +
   1.934 +   png_ptr->transformations |= (PNG_EXPAND_16 | PNG_EXPAND | PNG_EXPAND_tRNS);
   1.935 +}
   1.936 +#endif
   1.937 +
   1.938 +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
   1.939 +void PNGAPI
   1.940 +png_set_gray_to_rgb(png_structrp png_ptr)
   1.941 +{
   1.942 +   png_debug(1, "in png_set_gray_to_rgb");
   1.943 +
   1.944 +   if (!png_rtran_ok(png_ptr, 0))
   1.945 +      return;
   1.946 +
   1.947 +   /* Because rgb must be 8 bits or more: */
   1.948 +   png_set_expand_gray_1_2_4_to_8(png_ptr);
   1.949 +   png_ptr->transformations |= PNG_GRAY_TO_RGB;
   1.950 +}
   1.951 +#endif
   1.952 +
   1.953 +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
   1.954 +void PNGFAPI
   1.955 +png_set_rgb_to_gray_fixed(png_structrp png_ptr, int error_action,
   1.956 +    png_fixed_point red, png_fixed_point green)
   1.957 +{
   1.958 +   png_debug(1, "in png_set_rgb_to_gray");
   1.959 +
   1.960 +   /* Need the IHDR here because of the check on color_type below. */
   1.961 +   /* TODO: fix this */
   1.962 +   if (!png_rtran_ok(png_ptr, 1))
   1.963 +      return;
   1.964 +
   1.965 +   switch(error_action)
   1.966 +   {
   1.967 +      case PNG_ERROR_ACTION_NONE:
   1.968 +         png_ptr->transformations |= PNG_RGB_TO_GRAY;
   1.969 +         break;
   1.970 +
   1.971 +      case PNG_ERROR_ACTION_WARN:
   1.972 +         png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN;
   1.973 +         break;
   1.974 +
   1.975 +      case PNG_ERROR_ACTION_ERROR:
   1.976 +         png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR;
   1.977 +         break;
   1.978 +
   1.979 +      default:
   1.980 +         png_error(png_ptr, "invalid error action to rgb_to_gray");
   1.981 +         break;
   1.982 +   }
   1.983 +
   1.984 +   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
   1.985 +#ifdef PNG_READ_EXPAND_SUPPORTED
   1.986 +      png_ptr->transformations |= PNG_EXPAND;
   1.987 +#else
   1.988 +   {
   1.989 +      /* Make this an error in 1.6 because otherwise the application may assume
   1.990 +       * that it just worked and get a memory overwrite.
   1.991 +       */
   1.992 +      png_error(png_ptr,
   1.993 +        "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED");
   1.994 +
   1.995 +      /* png_ptr->transformations &= ~PNG_RGB_TO_GRAY; */
   1.996 +   }
   1.997 +#endif
   1.998 +   {
   1.999 +      if (red >= 0 && green >= 0 && red + green <= PNG_FP_1)
  1.1000 +      {
  1.1001 +         png_uint_16 red_int, green_int;
  1.1002 +
  1.1003 +         /* NOTE: this calculation does not round, but this behavior is retained
  1.1004 +          * for consistency, the inaccuracy is very small.  The code here always
  1.1005 +          * overwrites the coefficients, regardless of whether they have been
  1.1006 +          * defaulted or set already.
  1.1007 +          */
  1.1008 +         red_int = (png_uint_16)(((png_uint_32)red*32768)/100000);
  1.1009 +         green_int = (png_uint_16)(((png_uint_32)green*32768)/100000);
  1.1010 +
  1.1011 +         png_ptr->rgb_to_gray_red_coeff   = red_int;
  1.1012 +         png_ptr->rgb_to_gray_green_coeff = green_int;
  1.1013 +         png_ptr->rgb_to_gray_coefficients_set = 1;
  1.1014 +      }
  1.1015 +
  1.1016 +      else
  1.1017 +      {
  1.1018 +         if (red >= 0 && green >= 0)
  1.1019 +            png_app_warning(png_ptr,
  1.1020 +               "ignoring out of range rgb_to_gray coefficients");
  1.1021 +
  1.1022 +         /* Use the defaults, from the cHRM chunk if set, else the historical
  1.1023 +          * values which are close to the sRGB/HDTV/ITU-Rec 709 values.  See
  1.1024 +          * png_do_rgb_to_gray for more discussion of the values.  In this case
  1.1025 +          * the coefficients are not marked as 'set' and are not overwritten if
  1.1026 +          * something has already provided a default.
  1.1027 +          */
  1.1028 +         if (png_ptr->rgb_to_gray_red_coeff == 0 &&
  1.1029 +            png_ptr->rgb_to_gray_green_coeff == 0)
  1.1030 +         {
  1.1031 +            png_ptr->rgb_to_gray_red_coeff   = 6968;
  1.1032 +            png_ptr->rgb_to_gray_green_coeff = 23434;
  1.1033 +            /* png_ptr->rgb_to_gray_blue_coeff  = 2366; */
  1.1034 +         }
  1.1035 +      }
  1.1036 +   }
  1.1037 +}
  1.1038 +
  1.1039 +#ifdef PNG_FLOATING_POINT_SUPPORTED
  1.1040 +/* Convert a RGB image to a grayscale of the same width.  This allows us,
  1.1041 + * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image.
  1.1042 + */
  1.1043 +
  1.1044 +void PNGAPI
  1.1045 +png_set_rgb_to_gray(png_structrp png_ptr, int error_action, double red,
  1.1046 +   double green)
  1.1047 +{
  1.1048 +   png_set_rgb_to_gray_fixed(png_ptr, error_action,
  1.1049 +      png_fixed(png_ptr, red, "rgb to gray red coefficient"),
  1.1050 +      png_fixed(png_ptr, green, "rgb to gray green coefficient"));
  1.1051 +}
  1.1052 +#endif /* FLOATING POINT */
  1.1053 +
  1.1054 +#endif /* RGB_TO_GRAY */
  1.1055 +
  1.1056 +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
  1.1057 +    defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
  1.1058 +void PNGAPI
  1.1059 +png_set_read_user_transform_fn(png_structrp png_ptr, png_user_transform_ptr
  1.1060 +    read_user_transform_fn)
  1.1061 +{
  1.1062 +   png_debug(1, "in png_set_read_user_transform_fn");
  1.1063 +
  1.1064 +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
  1.1065 +   png_ptr->transformations |= PNG_USER_TRANSFORM;
  1.1066 +   png_ptr->read_user_transform_fn = read_user_transform_fn;
  1.1067 +#endif
  1.1068 +}
  1.1069 +#endif
  1.1070 +
  1.1071 +#ifdef PNG_READ_TRANSFORMS_SUPPORTED
  1.1072 +#ifdef PNG_READ_GAMMA_SUPPORTED
  1.1073 +/* In the case of gamma transformations only do transformations on images where
  1.1074 + * the [file] gamma and screen_gamma are not close reciprocals, otherwise it
  1.1075 + * slows things down slightly, and also needlessly introduces small errors.
  1.1076 + */
  1.1077 +static int /* PRIVATE */
  1.1078 +png_gamma_threshold(png_fixed_point screen_gamma, png_fixed_point file_gamma)
  1.1079 +{
  1.1080 +   /* PNG_GAMMA_THRESHOLD is the threshold for performing gamma
  1.1081 +    * correction as a difference of the overall transform from 1.0
  1.1082 +    *
  1.1083 +    * We want to compare the threshold with s*f - 1, if we get
  1.1084 +    * overflow here it is because of wacky gamma values so we
  1.1085 +    * turn on processing anyway.
  1.1086 +    */
  1.1087 +   png_fixed_point gtest;
  1.1088 +   return !png_muldiv(&gtest, screen_gamma, file_gamma, PNG_FP_1) ||
  1.1089 +       png_gamma_significant(gtest);
  1.1090 +}
  1.1091 +#endif
  1.1092 +
  1.1093 +/* Initialize everything needed for the read.  This includes modifying
  1.1094 + * the palette.
  1.1095 + */
  1.1096 +
  1.1097 +/*For the moment 'png_init_palette_transformations' and
  1.1098 + * 'png_init_rgb_transformations' only do some flag canceling optimizations.
  1.1099 + * The intent is that these two routines should have palette or rgb operations
  1.1100 + * extracted from 'png_init_read_transformations'.
  1.1101 + */
  1.1102 +static void /* PRIVATE */
  1.1103 +png_init_palette_transformations(png_structrp png_ptr)
  1.1104 +{
  1.1105 +   /* Called to handle the (input) palette case.  In png_do_read_transformations
  1.1106 +    * the first step is to expand the palette if requested, so this code must
  1.1107 +    * take care to only make changes that are invariant with respect to the
  1.1108 +    * palette expansion, or only do them if there is no expansion.
  1.1109 +    *
  1.1110 +    * STRIP_ALPHA has already been handled in the caller (by setting num_trans
  1.1111 +    * to 0.)
  1.1112 +    */
  1.1113 +   int input_has_alpha = 0;
  1.1114 +   int input_has_transparency = 0;
  1.1115 +
  1.1116 +   if (png_ptr->num_trans > 0)
  1.1117 +   {
  1.1118 +      int i;
  1.1119 +
  1.1120 +      /* Ignore if all the entries are opaque (unlikely!) */
  1.1121 +      for (i=0; i<png_ptr->num_trans; ++i)
  1.1122 +      {
  1.1123 +         if (png_ptr->trans_alpha[i] == 255)
  1.1124 +            continue;
  1.1125 +         else if (png_ptr->trans_alpha[i] == 0)
  1.1126 +            input_has_transparency = 1;
  1.1127 +         else
  1.1128 +         {
  1.1129 +            input_has_transparency = 1;
  1.1130 +            input_has_alpha = 1;
  1.1131 +            break;
  1.1132 +         }
  1.1133 +      }
  1.1134 +   }
  1.1135 +
  1.1136 +   /* If no alpha we can optimize. */
  1.1137 +   if (!input_has_alpha)
  1.1138 +   {
  1.1139 +      /* Any alpha means background and associative alpha processing is
  1.1140 +       * required, however if the alpha is 0 or 1 throughout OPTIMIZE_ALPHA
  1.1141 +       * and ENCODE_ALPHA are irrelevant.
  1.1142 +       */
  1.1143 +      png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
  1.1144 +      png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
  1.1145 +
  1.1146 +      if (!input_has_transparency)
  1.1147 +         png_ptr->transformations &= ~(PNG_COMPOSE | PNG_BACKGROUND_EXPAND);
  1.1148 +   }
  1.1149 +
  1.1150 +#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
  1.1151 +   /* png_set_background handling - deals with the complexity of whether the
  1.1152 +    * background color is in the file format or the screen format in the case
  1.1153 +    * where an 'expand' will happen.
  1.1154 +    */
  1.1155 +
  1.1156 +   /* The following code cannot be entered in the alpha pre-multiplication case
  1.1157 +    * because PNG_BACKGROUND_EXPAND is cancelled below.
  1.1158 +    */
  1.1159 +   if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
  1.1160 +       (png_ptr->transformations & PNG_EXPAND))
  1.1161 +   {
  1.1162 +      {
  1.1163 +         png_ptr->background.red   =
  1.1164 +             png_ptr->palette[png_ptr->background.index].red;
  1.1165 +         png_ptr->background.green =
  1.1166 +             png_ptr->palette[png_ptr->background.index].green;
  1.1167 +         png_ptr->background.blue  =
  1.1168 +             png_ptr->palette[png_ptr->background.index].blue;
  1.1169 +
  1.1170 +#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
  1.1171 +        if (png_ptr->transformations & PNG_INVERT_ALPHA)
  1.1172 +        {
  1.1173 +           if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
  1.1174 +           {
  1.1175 +              /* Invert the alpha channel (in tRNS) unless the pixels are
  1.1176 +               * going to be expanded, in which case leave it for later
  1.1177 +               */
  1.1178 +              int i, istop = png_ptr->num_trans;
  1.1179 +
  1.1180 +              for (i=0; i<istop; i++)
  1.1181 +                 png_ptr->trans_alpha[i] = (png_byte)(255 -
  1.1182 +                    png_ptr->trans_alpha[i]);
  1.1183 +           }
  1.1184 +        }
  1.1185 +#endif /* PNG_READ_INVERT_ALPHA_SUPPORTED */
  1.1186 +      }
  1.1187 +   } /* background expand and (therefore) no alpha association. */
  1.1188 +#endif /* PNG_READ_EXPAND_SUPPORTED && PNG_READ_BACKGROUND_SUPPORTED */
  1.1189 +}
  1.1190 +
  1.1191 +static void /* PRIVATE */
  1.1192 +png_init_rgb_transformations(png_structrp png_ptr)
  1.1193 +{
  1.1194 +   /* Added to libpng-1.5.4: check the color type to determine whether there
  1.1195 +    * is any alpha or transparency in the image and simply cancel the
  1.1196 +    * background and alpha mode stuff if there isn't.
  1.1197 +    */
  1.1198 +   int input_has_alpha = (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0;
  1.1199 +   int input_has_transparency = png_ptr->num_trans > 0;
  1.1200 +
  1.1201 +   /* If no alpha we can optimize. */
  1.1202 +   if (!input_has_alpha)
  1.1203 +   {
  1.1204 +      /* Any alpha means background and associative alpha processing is
  1.1205 +       * required, however if the alpha is 0 or 1 throughout OPTIMIZE_ALPHA
  1.1206 +       * and ENCODE_ALPHA are irrelevant.
  1.1207 +       */
  1.1208 +#     ifdef PNG_READ_ALPHA_MODE_SUPPORTED
  1.1209 +         png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
  1.1210 +         png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
  1.1211 +#     endif
  1.1212 +
  1.1213 +      if (!input_has_transparency)
  1.1214 +         png_ptr->transformations &= ~(PNG_COMPOSE | PNG_BACKGROUND_EXPAND);
  1.1215 +   }
  1.1216 +
  1.1217 +#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
  1.1218 +   /* png_set_background handling - deals with the complexity of whether the
  1.1219 +    * background color is in the file format or the screen format in the case
  1.1220 +    * where an 'expand' will happen.
  1.1221 +    */
  1.1222 +
  1.1223 +   /* The following code cannot be entered in the alpha pre-multiplication case
  1.1224 +    * because PNG_BACKGROUND_EXPAND is cancelled below.
  1.1225 +    */
  1.1226 +   if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
  1.1227 +       (png_ptr->transformations & PNG_EXPAND) &&
  1.1228 +       !(png_ptr->color_type & PNG_COLOR_MASK_COLOR))
  1.1229 +       /* i.e., GRAY or GRAY_ALPHA */
  1.1230 +   {
  1.1231 +      {
  1.1232 +         /* Expand background and tRNS chunks */
  1.1233 +         int gray = png_ptr->background.gray;
  1.1234 +         int trans_gray = png_ptr->trans_color.gray;
  1.1235 +
  1.1236 +         switch (png_ptr->bit_depth)
  1.1237 +         {
  1.1238 +            case 1:
  1.1239 +               gray *= 0xff;
  1.1240 +               trans_gray *= 0xff;
  1.1241 +               break;
  1.1242 +
  1.1243 +            case 2:
  1.1244 +               gray *= 0x55;
  1.1245 +               trans_gray *= 0x55;
  1.1246 +               break;
  1.1247 +
  1.1248 +            case 4:
  1.1249 +               gray *= 0x11;
  1.1250 +               trans_gray *= 0x11;
  1.1251 +               break;
  1.1252 +
  1.1253 +            default:
  1.1254 +
  1.1255 +            case 8:
  1.1256 +               /* FALL THROUGH (Already 8 bits) */
  1.1257 +
  1.1258 +            case 16:
  1.1259 +               /* Already a full 16 bits */
  1.1260 +               break;
  1.1261 +         }
  1.1262 +
  1.1263 +         png_ptr->background.red = png_ptr->background.green =
  1.1264 +            png_ptr->background.blue = (png_uint_16)gray;
  1.1265 +
  1.1266 +         if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
  1.1267 +         {
  1.1268 +            png_ptr->trans_color.red = png_ptr->trans_color.green =
  1.1269 +               png_ptr->trans_color.blue = (png_uint_16)trans_gray;
  1.1270 +         }
  1.1271 +      }
  1.1272 +   } /* background expand and (therefore) no alpha association. */
  1.1273 +#endif /* PNG_READ_EXPAND_SUPPORTED && PNG_READ_BACKGROUND_SUPPORTED */
  1.1274 +}
  1.1275 +
  1.1276 +void /* PRIVATE */
  1.1277 +png_init_read_transformations(png_structrp png_ptr)
  1.1278 +{
  1.1279 +   png_debug(1, "in png_init_read_transformations");
  1.1280 +
  1.1281 +   /* This internal function is called from png_read_start_row in pngrutil.c
  1.1282 +    * and it is called before the 'rowbytes' calculation is done, so the code
  1.1283 +    * in here can change or update the transformations flags.
  1.1284 +    *
  1.1285 +    * First do updates that do not depend on the details of the PNG image data
  1.1286 +    * being processed.
  1.1287 +    */
  1.1288 +
  1.1289 +#ifdef PNG_READ_GAMMA_SUPPORTED
  1.1290 +   /* Prior to 1.5.4 these tests were performed from png_set_gamma, 1.5.4 adds
  1.1291 +    * png_set_alpha_mode and this is another source for a default file gamma so
  1.1292 +    * the test needs to be performed later - here.  In addition prior to 1.5.4
  1.1293 +    * the tests were repeated for the PALETTE color type here - this is no
  1.1294 +    * longer necessary (and doesn't seem to have been necessary before.)
  1.1295 +    */
  1.1296 +   {
  1.1297 +      /* The following temporary indicates if overall gamma correction is
  1.1298 +       * required.
  1.1299 +       */
  1.1300 +      int gamma_correction = 0;
  1.1301 +
  1.1302 +      if (png_ptr->colorspace.gamma != 0) /* has been set */
  1.1303 +      {
  1.1304 +         if (png_ptr->screen_gamma != 0) /* screen set too */
  1.1305 +            gamma_correction = png_gamma_threshold(png_ptr->colorspace.gamma,
  1.1306 +               png_ptr->screen_gamma);
  1.1307 +
  1.1308 +         else
  1.1309 +            /* Assume the output matches the input; a long time default behavior
  1.1310 +             * of libpng, although the standard has nothing to say about this.
  1.1311 +             */
  1.1312 +            png_ptr->screen_gamma = png_reciprocal(png_ptr->colorspace.gamma);
  1.1313 +      }
  1.1314 +
  1.1315 +      else if (png_ptr->screen_gamma != 0)
  1.1316 +         /* The converse - assume the file matches the screen, note that this
  1.1317 +          * perhaps undesireable default can (from 1.5.4) be changed by calling
  1.1318 +          * png_set_alpha_mode (even if the alpha handling mode isn't required
  1.1319 +          * or isn't changed from the default.)
  1.1320 +          */
  1.1321 +         png_ptr->colorspace.gamma = png_reciprocal(png_ptr->screen_gamma);
  1.1322 +
  1.1323 +      else /* neither are set */
  1.1324 +         /* Just in case the following prevents any processing - file and screen
  1.1325 +          * are both assumed to be linear and there is no way to introduce a
  1.1326 +          * third gamma value other than png_set_background with 'UNIQUE', and,
  1.1327 +          * prior to 1.5.4
  1.1328 +          */
  1.1329 +         png_ptr->screen_gamma = png_ptr->colorspace.gamma = PNG_FP_1;
  1.1330 +
  1.1331 +      /* We have a gamma value now. */
  1.1332 +      png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;
  1.1333 +
  1.1334 +      /* Now turn the gamma transformation on or off as appropriate.  Notice
  1.1335 +       * that PNG_GAMMA just refers to the file->screen correction.  Alpha
  1.1336 +       * composition may independently cause gamma correction because it needs
  1.1337 +       * linear data (e.g. if the file has a gAMA chunk but the screen gamma
  1.1338 +       * hasn't been specified.)  In any case this flag may get turned off in
  1.1339 +       * the code immediately below if the transform can be handled outside the
  1.1340 +       * row loop.
  1.1341 +       */
  1.1342 +      if (gamma_correction)
  1.1343 +         png_ptr->transformations |= PNG_GAMMA;
  1.1344 +
  1.1345 +      else
  1.1346 +         png_ptr->transformations &= ~PNG_GAMMA;
  1.1347 +   }
  1.1348 +#endif
  1.1349 +
  1.1350 +   /* Certain transformations have the effect of preventing other
  1.1351 +    * transformations that happen afterward in png_do_read_transformations,
  1.1352 +    * resolve the interdependencies here.  From the code of
  1.1353 +    * png_do_read_transformations the order is:
  1.1354 +    *
  1.1355 +    *  1) PNG_EXPAND (including PNG_EXPAND_tRNS)
  1.1356 +    *  2) PNG_STRIP_ALPHA (if no compose)
  1.1357 +    *  3) PNG_RGB_TO_GRAY
  1.1358 +    *  4) PNG_GRAY_TO_RGB iff !PNG_BACKGROUND_IS_GRAY
  1.1359 +    *  5) PNG_COMPOSE
  1.1360 +    *  6) PNG_GAMMA
  1.1361 +    *  7) PNG_STRIP_ALPHA (if compose)
  1.1362 +    *  8) PNG_ENCODE_ALPHA
  1.1363 +    *  9) PNG_SCALE_16_TO_8
  1.1364 +    * 10) PNG_16_TO_8
  1.1365 +    * 11) PNG_QUANTIZE (converts to palette)
  1.1366 +    * 12) PNG_EXPAND_16
  1.1367 +    * 13) PNG_GRAY_TO_RGB iff PNG_BACKGROUND_IS_GRAY
  1.1368 +    * 14) PNG_INVERT_MONO
  1.1369 +    * 15) PNG_INVERT_ALPHA
  1.1370 +    * 16) PNG_SHIFT
  1.1371 +    * 17) PNG_PACK
  1.1372 +    * 18) PNG_BGR
  1.1373 +    * 19) PNG_PACKSWAP
  1.1374 +    * 20) PNG_FILLER (includes PNG_ADD_ALPHA)
  1.1375 +    * 21) PNG_SWAP_ALPHA
  1.1376 +    * 22) PNG_SWAP_BYTES
  1.1377 +    * 23) PNG_USER_TRANSFORM [must be last]
  1.1378 +    */
  1.1379 +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
  1.1380 +   if ((png_ptr->transformations & PNG_STRIP_ALPHA) &&
  1.1381 +      !(png_ptr->transformations & PNG_COMPOSE))
  1.1382 +   {
  1.1383 +      /* Stripping the alpha channel happens immediately after the 'expand'
  1.1384 +       * transformations, before all other transformation, so it cancels out
  1.1385 +       * the alpha handling.  It has the side effect negating the effect of
  1.1386 +       * PNG_EXPAND_tRNS too:
  1.1387 +       */
  1.1388 +      png_ptr->transformations &= ~(PNG_BACKGROUND_EXPAND | PNG_ENCODE_ALPHA |
  1.1389 +         PNG_EXPAND_tRNS);
  1.1390 +      png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
  1.1391 +
  1.1392 +      /* Kill the tRNS chunk itself too.  Prior to 1.5.4 this did not happen
  1.1393 +       * so transparency information would remain just so long as it wasn't
  1.1394 +       * expanded.  This produces unexpected API changes if the set of things
  1.1395 +       * that do PNG_EXPAND_tRNS changes (perfectly possible given the
  1.1396 +       * documentation - which says ask for what you want, accept what you
  1.1397 +       * get.)  This makes the behavior consistent from 1.5.4:
  1.1398 +       */
  1.1399 +      png_ptr->num_trans = 0;
  1.1400 +   }
  1.1401 +#endif /* STRIP_ALPHA supported, no COMPOSE */
  1.1402 +
  1.1403 +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
  1.1404 +   /* If the screen gamma is about 1.0 then the OPTIMIZE_ALPHA and ENCODE_ALPHA
  1.1405 +    * settings will have no effect.
  1.1406 +    */
  1.1407 +   if (!png_gamma_significant(png_ptr->screen_gamma))
  1.1408 +   {
  1.1409 +      png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
  1.1410 +      png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
  1.1411 +   }
  1.1412 +#endif
  1.1413 +
  1.1414 +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
  1.1415 +   /* Make sure the coefficients for the rgb to gray conversion are set
  1.1416 +    * appropriately.
  1.1417 +    */
  1.1418 +   if (png_ptr->transformations & PNG_RGB_TO_GRAY)
  1.1419 +      png_colorspace_set_rgb_coefficients(png_ptr);
  1.1420 +#endif
  1.1421 +
  1.1422 +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
  1.1423 +#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
  1.1424 +   /* Detect gray background and attempt to enable optimization for
  1.1425 +    * gray --> RGB case.
  1.1426 +    *
  1.1427 +    * Note:  if PNG_BACKGROUND_EXPAND is set and color_type is either RGB or
  1.1428 +    * RGB_ALPHA (in which case need_expand is superfluous anyway), the
  1.1429 +    * background color might actually be gray yet not be flagged as such.
  1.1430 +    * This is not a problem for the current code, which uses
  1.1431 +    * PNG_BACKGROUND_IS_GRAY only to decide when to do the
  1.1432 +    * png_do_gray_to_rgb() transformation.
  1.1433 +    *
  1.1434 +    * TODO: this code needs to be revised to avoid the complexity and
  1.1435 +    * interdependencies.  The color type of the background should be recorded in
  1.1436 +    * png_set_background, along with the bit depth, then the code has a record
  1.1437 +    * of exactly what color space the background is currently in.
  1.1438 +    */
  1.1439 +   if (png_ptr->transformations & PNG_BACKGROUND_EXPAND)
  1.1440 +   {
  1.1441 +      /* PNG_BACKGROUND_EXPAND: the background is in the file color space, so if
  1.1442 +       * the file was grayscale the background value is gray.
  1.1443 +       */
  1.1444 +      if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR))
  1.1445 +         png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
  1.1446 +   }
  1.1447 +
  1.1448 +   else if (png_ptr->transformations & PNG_COMPOSE)
  1.1449 +   {
  1.1450 +      /* PNG_COMPOSE: png_set_background was called with need_expand false,
  1.1451 +       * so the color is in the color space of the output or png_set_alpha_mode
  1.1452 +       * was called and the color is black.  Ignore RGB_TO_GRAY because that
  1.1453 +       * happens before GRAY_TO_RGB.
  1.1454 +       */
  1.1455 +      if (png_ptr->transformations & PNG_GRAY_TO_RGB)
  1.1456 +      {
  1.1457 +         if (png_ptr->background.red == png_ptr->background.green &&
  1.1458 +             png_ptr->background.red == png_ptr->background.blue)
  1.1459 +         {
  1.1460 +            png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
  1.1461 +            png_ptr->background.gray = png_ptr->background.red;
  1.1462 +         }
  1.1463 +      }
  1.1464 +   }
  1.1465 +#endif /* PNG_READ_EXPAND_SUPPORTED && PNG_READ_BACKGROUND_SUPPORTED */
  1.1466 +#endif /* PNG_READ_GRAY_TO_RGB_SUPPORTED */
  1.1467 +
  1.1468 +   /* For indexed PNG data (PNG_COLOR_TYPE_PALETTE) many of the transformations
  1.1469 +    * can be performed directly on the palette, and some (such as rgb to gray)
  1.1470 +    * can be optimized inside the palette.  This is particularly true of the
  1.1471 +    * composite (background and alpha) stuff, which can be pretty much all done
  1.1472 +    * in the palette even if the result is expanded to RGB or gray afterward.
  1.1473 +    *
  1.1474 +    * NOTE: this is Not Yet Implemented, the code behaves as in 1.5.1 and
  1.1475 +    * earlier and the palette stuff is actually handled on the first row.  This
  1.1476 +    * leads to the reported bug that the palette returned by png_get_PLTE is not
  1.1477 +    * updated.
  1.1478 +    */
  1.1479 +   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
  1.1480 +      png_init_palette_transformations(png_ptr);
  1.1481 +
  1.1482 +   else
  1.1483 +      png_init_rgb_transformations(png_ptr);
  1.1484 +
  1.1485 +#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
  1.1486 +   defined(PNG_READ_EXPAND_16_SUPPORTED)
  1.1487 +   if ((png_ptr->transformations & PNG_EXPAND_16) &&
  1.1488 +      (png_ptr->transformations & PNG_COMPOSE) &&
  1.1489 +      !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
  1.1490 +      png_ptr->bit_depth != 16)
  1.1491 +   {
  1.1492 +      /* TODO: fix this.  Because the expand_16 operation is after the compose
  1.1493 +       * handling the background color must be 8, not 16, bits deep, but the
  1.1494 +       * application will supply a 16-bit value so reduce it here.
  1.1495 +       *
  1.1496 +       * The PNG_BACKGROUND_EXPAND code above does not expand to 16 bits at
  1.1497 +       * present, so that case is ok (until do_expand_16 is moved.)
  1.1498 +       *
  1.1499 +       * NOTE: this discards the low 16 bits of the user supplied background
  1.1500 +       * color, but until expand_16 works properly there is no choice!
  1.1501 +       */
  1.1502 +#     define CHOP(x) (x)=((png_uint_16)PNG_DIV257(x))
  1.1503 +      CHOP(png_ptr->background.red);
  1.1504 +      CHOP(png_ptr->background.green);
  1.1505 +      CHOP(png_ptr->background.blue);
  1.1506 +      CHOP(png_ptr->background.gray);
  1.1507 +#     undef CHOP
  1.1508 +   }
  1.1509 +#endif /* PNG_READ_BACKGROUND_SUPPORTED && PNG_READ_EXPAND_16_SUPPORTED */
  1.1510 +
  1.1511 +#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
  1.1512 +   (defined(PNG_READ_SCALE_16_TO_8_SUPPORTED) || \
  1.1513 +   defined(PNG_READ_STRIP_16_TO_8_SUPPORTED))
  1.1514 +   if ((png_ptr->transformations & (PNG_16_TO_8|PNG_SCALE_16_TO_8)) &&
  1.1515 +      (png_ptr->transformations & PNG_COMPOSE) &&
  1.1516 +      !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
  1.1517 +      png_ptr->bit_depth == 16)
  1.1518 +   {
  1.1519 +      /* On the other hand, if a 16-bit file is to be reduced to 8-bits per
  1.1520 +       * component this will also happen after PNG_COMPOSE and so the background
  1.1521 +       * color must be pre-expanded here.
  1.1522 +       *
  1.1523 +       * TODO: fix this too.
  1.1524 +       */
  1.1525 +      png_ptr->background.red = (png_uint_16)(png_ptr->background.red * 257);
  1.1526 +      png_ptr->background.green =
  1.1527 +         (png_uint_16)(png_ptr->background.green * 257);
  1.1528 +      png_ptr->background.blue = (png_uint_16)(png_ptr->background.blue * 257);
  1.1529 +      png_ptr->background.gray = (png_uint_16)(png_ptr->background.gray * 257);
  1.1530 +   }
  1.1531 +#endif
  1.1532 +
  1.1533 +   /* NOTE: below 'PNG_READ_ALPHA_MODE_SUPPORTED' is presumed to also enable the
  1.1534 +    * background support (see the comments in scripts/pnglibconf.dfa), this
  1.1535 +    * allows pre-multiplication of the alpha channel to be implemented as
  1.1536 +    * compositing on black.  This is probably sub-optimal and has been done in
  1.1537 +    * 1.5.4 betas simply to enable external critique and testing (i.e. to
  1.1538 +    * implement the new API quickly, without lots of internal changes.)
  1.1539 +    */
  1.1540 +
  1.1541 +#ifdef PNG_READ_GAMMA_SUPPORTED
  1.1542 +#  ifdef PNG_READ_BACKGROUND_SUPPORTED
  1.1543 +      /* Includes ALPHA_MODE */
  1.1544 +      png_ptr->background_1 = png_ptr->background;
  1.1545 +#  endif
  1.1546 +
  1.1547 +   /* This needs to change - in the palette image case a whole set of tables are
  1.1548 +    * built when it would be quicker to just calculate the correct value for
  1.1549 +    * each palette entry directly.  Also, the test is too tricky - why check
  1.1550 +    * PNG_RGB_TO_GRAY if PNG_GAMMA is not set?  The answer seems to be that
  1.1551 +    * PNG_GAMMA is cancelled even if the gamma is known?  The test excludes the
  1.1552 +    * PNG_COMPOSE case, so apparently if there is no *overall* gamma correction
  1.1553 +    * the gamma tables will not be built even if composition is required on a
  1.1554 +    * gamma encoded value.
  1.1555 +    *
  1.1556 +    * In 1.5.4 this is addressed below by an additional check on the individual
  1.1557 +    * file gamma - if it is not 1.0 both RGB_TO_GRAY and COMPOSE need the
  1.1558 +    * tables.
  1.1559 +    */
  1.1560 +   if ((png_ptr->transformations & PNG_GAMMA)
  1.1561 +      || ((png_ptr->transformations & PNG_RGB_TO_GRAY)
  1.1562 +         && (png_gamma_significant(png_ptr->colorspace.gamma) ||
  1.1563 +            png_gamma_significant(png_ptr->screen_gamma)))
  1.1564 +      || ((png_ptr->transformations & PNG_COMPOSE)
  1.1565 +         && (png_gamma_significant(png_ptr->colorspace.gamma)
  1.1566 +            || png_gamma_significant(png_ptr->screen_gamma)
  1.1567 +#  ifdef PNG_READ_BACKGROUND_SUPPORTED
  1.1568 +            || (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_UNIQUE
  1.1569 +               && png_gamma_significant(png_ptr->background_gamma))
  1.1570 +#  endif
  1.1571 +      )) || ((png_ptr->transformations & PNG_ENCODE_ALPHA)
  1.1572 +         && png_gamma_significant(png_ptr->screen_gamma))
  1.1573 +      )
  1.1574 +   {
  1.1575 +      png_build_gamma_table(png_ptr, png_ptr->bit_depth);
  1.1576 +
  1.1577 +#ifdef PNG_READ_BACKGROUND_SUPPORTED
  1.1578 +      if (png_ptr->transformations & PNG_COMPOSE)
  1.1579 +      {
  1.1580 +         /* Issue a warning about this combination: because RGB_TO_GRAY is
  1.1581 +          * optimized to do the gamma transform if present yet do_background has
  1.1582 +          * to do the same thing if both options are set a
  1.1583 +          * double-gamma-correction happens.  This is true in all versions of
  1.1584 +          * libpng to date.
  1.1585 +          */
  1.1586 +         if (png_ptr->transformations & PNG_RGB_TO_GRAY)
  1.1587 +            png_warning(png_ptr,
  1.1588 +               "libpng does not support gamma+background+rgb_to_gray");
  1.1589 +
  1.1590 +         if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
  1.1591 +         {
  1.1592 +            /* We don't get to here unless there is a tRNS chunk with non-opaque
  1.1593 +             * entries - see the checking code at the start of this function.
  1.1594 +             */
  1.1595 +            png_color back, back_1;
  1.1596 +            png_colorp palette = png_ptr->palette;
  1.1597 +            int num_palette = png_ptr->num_palette;
  1.1598 +            int i;
  1.1599 +            if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
  1.1600 +            {
  1.1601 +
  1.1602 +               back.red = png_ptr->gamma_table[png_ptr->background.red];
  1.1603 +               back.green = png_ptr->gamma_table[png_ptr->background.green];
  1.1604 +               back.blue = png_ptr->gamma_table[png_ptr->background.blue];
  1.1605 +
  1.1606 +               back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
  1.1607 +               back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
  1.1608 +               back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
  1.1609 +            }
  1.1610 +            else
  1.1611 +            {
  1.1612 +               png_fixed_point g, gs;
  1.1613 +
  1.1614 +               switch (png_ptr->background_gamma_type)
  1.1615 +               {
  1.1616 +                  case PNG_BACKGROUND_GAMMA_SCREEN:
  1.1617 +                     g = (png_ptr->screen_gamma);
  1.1618 +                     gs = PNG_FP_1;
  1.1619 +                     break;
  1.1620 +
  1.1621 +                  case PNG_BACKGROUND_GAMMA_FILE:
  1.1622 +                     g = png_reciprocal(png_ptr->colorspace.gamma);
  1.1623 +                     gs = png_reciprocal2(png_ptr->colorspace.gamma,
  1.1624 +                        png_ptr->screen_gamma);
  1.1625 +                     break;
  1.1626 +
  1.1627 +                  case PNG_BACKGROUND_GAMMA_UNIQUE:
  1.1628 +                     g = png_reciprocal(png_ptr->background_gamma);
  1.1629 +                     gs = png_reciprocal2(png_ptr->background_gamma,
  1.1630 +                        png_ptr->screen_gamma);
  1.1631 +                     break;
  1.1632 +                  default:
  1.1633 +                     g = PNG_FP_1;    /* back_1 */
  1.1634 +                     gs = PNG_FP_1;   /* back */
  1.1635 +                     break;
  1.1636 +               }
  1.1637 +
  1.1638 +               if (png_gamma_significant(gs))
  1.1639 +               {
  1.1640 +                  back.red = png_gamma_8bit_correct(png_ptr->background.red,
  1.1641 +                      gs);
  1.1642 +                  back.green = png_gamma_8bit_correct(png_ptr->background.green,
  1.1643 +                      gs);
  1.1644 +                  back.blue = png_gamma_8bit_correct(png_ptr->background.blue,
  1.1645 +                      gs);
  1.1646 +               }
  1.1647 +
  1.1648 +               else
  1.1649 +               {
  1.1650 +                  back.red   = (png_byte)png_ptr->background.red;
  1.1651 +                  back.green = (png_byte)png_ptr->background.green;
  1.1652 +                  back.blue  = (png_byte)png_ptr->background.blue;
  1.1653 +               }
  1.1654 +
  1.1655 +               if (png_gamma_significant(g))
  1.1656 +               {
  1.1657 +                  back_1.red = png_gamma_8bit_correct(png_ptr->background.red,
  1.1658 +                     g);
  1.1659 +                  back_1.green = png_gamma_8bit_correct(
  1.1660 +                     png_ptr->background.green, g);
  1.1661 +                  back_1.blue = png_gamma_8bit_correct(png_ptr->background.blue,
  1.1662 +                     g);
  1.1663 +               }
  1.1664 +
  1.1665 +               else
  1.1666 +               {
  1.1667 +                  back_1.red   = (png_byte)png_ptr->background.red;
  1.1668 +                  back_1.green = (png_byte)png_ptr->background.green;
  1.1669 +                  back_1.blue  = (png_byte)png_ptr->background.blue;
  1.1670 +               }
  1.1671 +            }
  1.1672 +
  1.1673 +            for (i = 0; i < num_palette; i++)
  1.1674 +            {
  1.1675 +               if (i < (int)png_ptr->num_trans &&
  1.1676 +                   png_ptr->trans_alpha[i] != 0xff)
  1.1677 +               {
  1.1678 +                  if (png_ptr->trans_alpha[i] == 0)
  1.1679 +                  {
  1.1680 +                     palette[i] = back;
  1.1681 +                  }
  1.1682 +                  else /* if (png_ptr->trans_alpha[i] != 0xff) */
  1.1683 +                  {
  1.1684 +                     png_byte v, w;
  1.1685 +
  1.1686 +                     v = png_ptr->gamma_to_1[palette[i].red];
  1.1687 +                     png_composite(w, v, png_ptr->trans_alpha[i], back_1.red);
  1.1688 +                     palette[i].red = png_ptr->gamma_from_1[w];
  1.1689 +
  1.1690 +                     v = png_ptr->gamma_to_1[palette[i].green];
  1.1691 +                     png_composite(w, v, png_ptr->trans_alpha[i], back_1.green);
  1.1692 +                     palette[i].green = png_ptr->gamma_from_1[w];
  1.1693 +
  1.1694 +                     v = png_ptr->gamma_to_1[palette[i].blue];
  1.1695 +                     png_composite(w, v, png_ptr->trans_alpha[i], back_1.blue);
  1.1696 +                     palette[i].blue = png_ptr->gamma_from_1[w];
  1.1697 +                  }
  1.1698 +               }
  1.1699 +               else
  1.1700 +               {
  1.1701 +                  palette[i].red = png_ptr->gamma_table[palette[i].red];
  1.1702 +                  palette[i].green = png_ptr->gamma_table[palette[i].green];
  1.1703 +                  palette[i].blue = png_ptr->gamma_table[palette[i].blue];
  1.1704 +               }
  1.1705 +            }
  1.1706 +
  1.1707 +            /* Prevent the transformations being done again.
  1.1708 +             *
  1.1709 +             * NOTE: this is highly dubious; it removes the transformations in
  1.1710 +             * place.  This seems inconsistent with the general treatment of the
  1.1711 +             * transformations elsewhere.
  1.1712 +             */
  1.1713 +            png_ptr->transformations &= ~(PNG_COMPOSE | PNG_GAMMA);
  1.1714 +         } /* color_type == PNG_COLOR_TYPE_PALETTE */
  1.1715 +
  1.1716 +         /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */
  1.1717 +         else /* color_type != PNG_COLOR_TYPE_PALETTE */
  1.1718 +         {
  1.1719 +            int gs_sig, g_sig;
  1.1720 +            png_fixed_point g = PNG_FP_1;  /* Correction to linear */
  1.1721 +            png_fixed_point gs = PNG_FP_1; /* Correction to screen */
  1.1722 +
  1.1723 +            switch (png_ptr->background_gamma_type)
  1.1724 +            {
  1.1725 +               case PNG_BACKGROUND_GAMMA_SCREEN:
  1.1726 +                  g = png_ptr->screen_gamma;
  1.1727 +                  /* gs = PNG_FP_1; */
  1.1728 +                  break;
  1.1729 +
  1.1730 +               case PNG_BACKGROUND_GAMMA_FILE:
  1.1731 +                  g = png_reciprocal(png_ptr->colorspace.gamma);
  1.1732 +                  gs = png_reciprocal2(png_ptr->colorspace.gamma,
  1.1733 +                     png_ptr->screen_gamma);
  1.1734 +                  break;
  1.1735 +
  1.1736 +               case PNG_BACKGROUND_GAMMA_UNIQUE:
  1.1737 +                  g = png_reciprocal(png_ptr->background_gamma);
  1.1738 +                  gs = png_reciprocal2(png_ptr->background_gamma,
  1.1739 +                      png_ptr->screen_gamma);
  1.1740 +                  break;
  1.1741 +
  1.1742 +               default:
  1.1743 +                  png_error(png_ptr, "invalid background gamma type");
  1.1744 +            }
  1.1745 +
  1.1746 +            g_sig = png_gamma_significant(g);
  1.1747 +            gs_sig = png_gamma_significant(gs);
  1.1748 +
  1.1749 +            if (g_sig)
  1.1750 +               png_ptr->background_1.gray = png_gamma_correct(png_ptr,
  1.1751 +                   png_ptr->background.gray, g);
  1.1752 +
  1.1753 +            if (gs_sig)
  1.1754 +               png_ptr->background.gray = png_gamma_correct(png_ptr,
  1.1755 +                   png_ptr->background.gray, gs);
  1.1756 +
  1.1757 +            if ((png_ptr->background.red != png_ptr->background.green) ||
  1.1758 +                (png_ptr->background.red != png_ptr->background.blue) ||
  1.1759 +                (png_ptr->background.red != png_ptr->background.gray))
  1.1760 +            {
  1.1761 +               /* RGB or RGBA with color background */
  1.1762 +               if (g_sig)
  1.1763 +               {
  1.1764 +                  png_ptr->background_1.red = png_gamma_correct(png_ptr,
  1.1765 +                      png_ptr->background.red, g);
  1.1766 +
  1.1767 +                  png_ptr->background_1.green = png_gamma_correct(png_ptr,
  1.1768 +                      png_ptr->background.green, g);
  1.1769 +
  1.1770 +                  png_ptr->background_1.blue = png_gamma_correct(png_ptr,
  1.1771 +                      png_ptr->background.blue, g);
  1.1772 +               }
  1.1773 +
  1.1774 +               if (gs_sig)
  1.1775 +               {
  1.1776 +                  png_ptr->background.red = png_gamma_correct(png_ptr,
  1.1777 +                      png_ptr->background.red, gs);
  1.1778 +
  1.1779 +                  png_ptr->background.green = png_gamma_correct(png_ptr,
  1.1780 +                      png_ptr->background.green, gs);
  1.1781 +
  1.1782 +                  png_ptr->background.blue = png_gamma_correct(png_ptr,
  1.1783 +                      png_ptr->background.blue, gs);
  1.1784 +               }
  1.1785 +            }
  1.1786 +
  1.1787 +            else
  1.1788 +            {
  1.1789 +               /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */
  1.1790 +               png_ptr->background_1.red = png_ptr->background_1.green
  1.1791 +                   = png_ptr->background_1.blue = png_ptr->background_1.gray;
  1.1792 +
  1.1793 +               png_ptr->background.red = png_ptr->background.green
  1.1794 +                   = png_ptr->background.blue = png_ptr->background.gray;
  1.1795 +            }
  1.1796 +
  1.1797 +            /* The background is now in screen gamma: */
  1.1798 +            png_ptr->background_gamma_type = PNG_BACKGROUND_GAMMA_SCREEN;
  1.1799 +         } /* color_type != PNG_COLOR_TYPE_PALETTE */
  1.1800 +      }/* png_ptr->transformations & PNG_BACKGROUND */
  1.1801 +
  1.1802 +      else
  1.1803 +      /* Transformation does not include PNG_BACKGROUND */
  1.1804 +#endif /* PNG_READ_BACKGROUND_SUPPORTED */
  1.1805 +      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE
  1.1806 +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
  1.1807 +         /* RGB_TO_GRAY needs to have non-gamma-corrected values! */
  1.1808 +         && ((png_ptr->transformations & PNG_EXPAND) == 0 ||
  1.1809 +         (png_ptr->transformations & PNG_RGB_TO_GRAY) == 0)
  1.1810 +#endif
  1.1811 +         )
  1.1812 +      {
  1.1813 +         png_colorp palette = png_ptr->palette;
  1.1814 +         int num_palette = png_ptr->num_palette;
  1.1815 +         int i;
  1.1816 +
  1.1817 +         /* NOTE: there are other transformations that should probably be in
  1.1818 +          * here too.
  1.1819 +          */
  1.1820 +         for (i = 0; i < num_palette; i++)
  1.1821 +         {
  1.1822 +            palette[i].red = png_ptr->gamma_table[palette[i].red];
  1.1823 +            palette[i].green = png_ptr->gamma_table[palette[i].green];
  1.1824 +            palette[i].blue = png_ptr->gamma_table[palette[i].blue];
  1.1825 +         }
  1.1826 +
  1.1827 +         /* Done the gamma correction. */
  1.1828 +         png_ptr->transformations &= ~PNG_GAMMA;
  1.1829 +      } /* color_type == PALETTE && !PNG_BACKGROUND transformation */
  1.1830 +   }
  1.1831 +#ifdef PNG_READ_BACKGROUND_SUPPORTED
  1.1832 +   else
  1.1833 +#endif
  1.1834 +#endif /* PNG_READ_GAMMA_SUPPORTED */
  1.1835 +
  1.1836 +#ifdef PNG_READ_BACKGROUND_SUPPORTED
  1.1837 +   /* No GAMMA transformation (see the hanging else 4 lines above) */
  1.1838 +   if ((png_ptr->transformations & PNG_COMPOSE) &&
  1.1839 +       (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))
  1.1840 +   {
  1.1841 +      int i;
  1.1842 +      int istop = (int)png_ptr->num_trans;
  1.1843 +      png_color back;
  1.1844 +      png_colorp palette = png_ptr->palette;
  1.1845 +
  1.1846 +      back.red   = (png_byte)png_ptr->background.red;
  1.1847 +      back.green = (png_byte)png_ptr->background.green;
  1.1848 +      back.blue  = (png_byte)png_ptr->background.blue;
  1.1849 +
  1.1850 +      for (i = 0; i < istop; i++)
  1.1851 +      {
  1.1852 +         if (png_ptr->trans_alpha[i] == 0)
  1.1853 +         {
  1.1854 +            palette[i] = back;
  1.1855 +         }
  1.1856 +
  1.1857 +         else if (png_ptr->trans_alpha[i] != 0xff)
  1.1858 +         {
  1.1859 +            /* The png_composite() macro is defined in png.h */
  1.1860 +            png_composite(palette[i].red, palette[i].red,
  1.1861 +                png_ptr->trans_alpha[i], back.red);
  1.1862 +
  1.1863 +            png_composite(palette[i].green, palette[i].green,
  1.1864 +                png_ptr->trans_alpha[i], back.green);
  1.1865 +
  1.1866 +            png_composite(palette[i].blue, palette[i].blue,
  1.1867 +                png_ptr->trans_alpha[i], back.blue);
  1.1868 +         }
  1.1869 +      }
  1.1870 +
  1.1871 +      png_ptr->transformations &= ~PNG_COMPOSE;
  1.1872 +   }
  1.1873 +#endif /* PNG_READ_BACKGROUND_SUPPORTED */
  1.1874 +
  1.1875 +#ifdef PNG_READ_SHIFT_SUPPORTED
  1.1876 +   if ((png_ptr->transformations & PNG_SHIFT) &&
  1.1877 +      !(png_ptr->transformations & PNG_EXPAND) &&
  1.1878 +       (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))
  1.1879 +   {
  1.1880 +      int i;
  1.1881 +      int istop = png_ptr->num_palette;
  1.1882 +      int shift = 8 - png_ptr->sig_bit.red;
  1.1883 +
  1.1884 +      png_ptr->transformations &= ~PNG_SHIFT;
  1.1885 +
  1.1886 +      /* significant bits can be in the range 1 to 7 for a meaninful result, if
  1.1887 +       * the number of significant bits is 0 then no shift is done (this is an
  1.1888 +       * error condition which is silently ignored.)
  1.1889 +       */
  1.1890 +      if (shift > 0 && shift < 8)
  1.1891 +         for (i=0; i<istop; ++i)
  1.1892 +         {
  1.1893 +            int component = png_ptr->palette[i].red;
  1.1894 +
  1.1895 +            component >>= shift;
  1.1896 +            png_ptr->palette[i].red = (png_byte)component;
  1.1897 +         }
  1.1898 +
  1.1899 +      shift = 8 - png_ptr->sig_bit.green;
  1.1900 +      if (shift > 0 && shift < 8)
  1.1901 +         for (i=0; i<istop; ++i)
  1.1902 +         {
  1.1903 +            int component = png_ptr->palette[i].green;
  1.1904 +
  1.1905 +            component >>= shift;
  1.1906 +            png_ptr->palette[i].green = (png_byte)component;
  1.1907 +         }
  1.1908 +
  1.1909 +      shift = 8 - png_ptr->sig_bit.blue;
  1.1910 +      if (shift > 0 && shift < 8)
  1.1911 +         for (i=0; i<istop; ++i)
  1.1912 +         {
  1.1913 +            int component = png_ptr->palette[i].blue;
  1.1914 +
  1.1915 +            component >>= shift;
  1.1916 +            png_ptr->palette[i].blue = (png_byte)component;
  1.1917 +         }
  1.1918 +   }
  1.1919 +#endif  /* PNG_READ_SHIFT_SUPPORTED */
  1.1920 +}
  1.1921 +
  1.1922 +/* Modify the info structure to reflect the transformations.  The
  1.1923 + * info should be updated so a PNG file could be written with it,
  1.1924 + * assuming the transformations result in valid PNG data.
  1.1925 + */
  1.1926 +void /* PRIVATE */
  1.1927 +png_read_transform_info(png_structrp png_ptr, png_inforp info_ptr)
  1.1928 +{
  1.1929 +   png_debug(1, "in png_read_transform_info");
  1.1930 +
  1.1931 +#ifdef PNG_READ_EXPAND_SUPPORTED
  1.1932 +   if (png_ptr->transformations & PNG_EXPAND)
  1.1933 +   {
  1.1934 +      if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
  1.1935 +      {
  1.1936 +         /* This check must match what actually happens in
  1.1937 +          * png_do_expand_palette; if it ever checks the tRNS chunk to see if
  1.1938 +          * it is all opaque we must do the same (at present it does not.)
  1.1939 +          */
  1.1940 +         if (png_ptr->num_trans > 0)
  1.1941 +            info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
  1.1942 +
  1.1943 +         else
  1.1944 +            info_ptr->color_type = PNG_COLOR_TYPE_RGB;
  1.1945 +
  1.1946 +         info_ptr->bit_depth = 8;
  1.1947 +         info_ptr->num_trans = 0;
  1.1948 +
  1.1949 +         if (png_ptr->palette == NULL)
  1.1950 +            png_error (png_ptr, "Palette is NULL in indexed image");
  1.1951 +      }
  1.1952 +      else
  1.1953 +      {
  1.1954 +         if (png_ptr->num_trans)
  1.1955 +         {
  1.1956 +            if (png_ptr->transformations & PNG_EXPAND_tRNS)
  1.1957 +               info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
  1.1958 +         }
  1.1959 +         if (info_ptr->bit_depth < 8)
  1.1960 +            info_ptr->bit_depth = 8;
  1.1961 +
  1.1962 +         info_ptr->num_trans = 0;
  1.1963 +      }
  1.1964 +   }
  1.1965 +#endif
  1.1966 +
  1.1967 +#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
  1.1968 +   defined(PNG_READ_ALPHA_MODE_SUPPORTED)
  1.1969 +   /* The following is almost certainly wrong unless the background value is in
  1.1970 +    * the screen space!
  1.1971 +    */
  1.1972 +   if (png_ptr->transformations & PNG_COMPOSE)
  1.1973 +      info_ptr->background = png_ptr->background;
  1.1974 +#endif
  1.1975 +
  1.1976 +#ifdef PNG_READ_GAMMA_SUPPORTED
  1.1977 +   /* The following used to be conditional on PNG_GAMMA (prior to 1.5.4),
  1.1978 +    * however it seems that the code in png_init_read_transformations, which has
  1.1979 +    * been called before this from png_read_update_info->png_read_start_row
  1.1980 +    * sometimes does the gamma transform and cancels the flag.
  1.1981 +    *
  1.1982 +    * TODO: this looks wrong; the info_ptr should end up with a gamma equal to
  1.1983 +    * the screen_gamma value.  The following probably results in weirdness if
  1.1984 +    * the info_ptr is used by the app after the rows have been read.
  1.1985 +    */
  1.1986 +   info_ptr->colorspace.gamma = png_ptr->colorspace.gamma;
  1.1987 +#endif
  1.1988 +
  1.1989 +   if (info_ptr->bit_depth == 16)
  1.1990 +   {
  1.1991 +#  ifdef PNG_READ_16BIT_SUPPORTED
  1.1992 +#     ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
  1.1993 +         if (png_ptr->transformations & PNG_SCALE_16_TO_8)
  1.1994 +            info_ptr->bit_depth = 8;
  1.1995 +#     endif
  1.1996 +
  1.1997 +#     ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
  1.1998 +         if (png_ptr->transformations & PNG_16_TO_8)
  1.1999 +            info_ptr->bit_depth = 8;
  1.2000 +#     endif
  1.2001 +
  1.2002 +#  else
  1.2003 +      /* No 16 bit support: force chopping 16-bit input down to 8, in this case
  1.2004 +       * the app program can chose if both APIs are available by setting the
  1.2005 +       * correct scaling to use.
  1.2006 +       */
  1.2007 +#     ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
  1.2008 +         /* For compatibility with previous versions use the strip method by
  1.2009 +          * default.  This code works because if PNG_SCALE_16_TO_8 is already
  1.2010 +          * set the code below will do that in preference to the chop.
  1.2011 +          */
  1.2012 +         png_ptr->transformations |= PNG_16_TO_8;
  1.2013 +         info_ptr->bit_depth = 8;
  1.2014 +#     else
  1.2015 +
  1.2016 +#        ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
  1.2017 +            png_ptr->transformations |= PNG_SCALE_16_TO_8;
  1.2018 +            info_ptr->bit_depth = 8;
  1.2019 +#        else
  1.2020 +
  1.2021 +            CONFIGURATION ERROR: you must enable at least one 16 to 8 method
  1.2022 +#        endif
  1.2023 +#    endif
  1.2024 +#endif /* !READ_16BIT_SUPPORTED */
  1.2025 +   }
  1.2026 +
  1.2027 +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
  1.2028 +   if (png_ptr->transformations & PNG_GRAY_TO_RGB)
  1.2029 +      info_ptr->color_type = (png_byte)(info_ptr->color_type |
  1.2030 +         PNG_COLOR_MASK_COLOR);
  1.2031 +#endif
  1.2032 +
  1.2033 +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
  1.2034 +   if (png_ptr->transformations & PNG_RGB_TO_GRAY)
  1.2035 +      info_ptr->color_type = (png_byte)(info_ptr->color_type &
  1.2036 +         ~PNG_COLOR_MASK_COLOR);
  1.2037 +#endif
  1.2038 +
  1.2039 +#ifdef PNG_READ_QUANTIZE_SUPPORTED
  1.2040 +   if (png_ptr->transformations & PNG_QUANTIZE)
  1.2041 +   {
  1.2042 +      if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
  1.2043 +          (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) &&
  1.2044 +          png_ptr->palette_lookup && info_ptr->bit_depth == 8)
  1.2045 +      {
  1.2046 +         info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
  1.2047 +      }
  1.2048 +   }
  1.2049 +#endif
  1.2050 +
  1.2051 +#ifdef PNG_READ_EXPAND_16_SUPPORTED
  1.2052 +   if (png_ptr->transformations & PNG_EXPAND_16 && info_ptr->bit_depth == 8 &&
  1.2053 +      info_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
  1.2054 +   {
  1.2055 +      info_ptr->bit_depth = 16;
  1.2056 +   }
  1.2057 +#endif
  1.2058 +
  1.2059 +#ifdef PNG_READ_PACK_SUPPORTED
  1.2060 +   if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8))
  1.2061 +      info_ptr->bit_depth = 8;
  1.2062 +#endif
  1.2063 +
  1.2064 +   if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
  1.2065 +      info_ptr->channels = 1;
  1.2066 +
  1.2067 +   else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
  1.2068 +      info_ptr->channels = 3;
  1.2069 +
  1.2070 +   else
  1.2071 +      info_ptr->channels = 1;
  1.2072 +
  1.2073 +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
  1.2074 +   if (png_ptr->transformations & PNG_STRIP_ALPHA)
  1.2075 +   {
  1.2076 +      info_ptr->color_type = (png_byte)(info_ptr->color_type &
  1.2077 +         ~PNG_COLOR_MASK_ALPHA);
  1.2078 +      info_ptr->num_trans = 0;
  1.2079 +   }
  1.2080 +#endif
  1.2081 +
  1.2082 +   if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
  1.2083 +      info_ptr->channels++;
  1.2084 +
  1.2085 +#ifdef PNG_READ_FILLER_SUPPORTED
  1.2086 +   /* STRIP_ALPHA and FILLER allowed:  MASK_ALPHA bit stripped above */
  1.2087 +   if ((png_ptr->transformations & PNG_FILLER) &&
  1.2088 +       ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
  1.2089 +       (info_ptr->color_type == PNG_COLOR_TYPE_GRAY)))
  1.2090 +   {
  1.2091 +      info_ptr->channels++;
  1.2092 +      /* If adding a true alpha channel not just filler */
  1.2093 +      if (png_ptr->transformations & PNG_ADD_ALPHA)
  1.2094 +         info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
  1.2095 +   }
  1.2096 +#endif
  1.2097 +
  1.2098 +#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \
  1.2099 +defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
  1.2100 +   if (png_ptr->transformations & PNG_USER_TRANSFORM)
  1.2101 +   {
  1.2102 +      if (info_ptr->bit_depth < png_ptr->user_transform_depth)
  1.2103 +         info_ptr->bit_depth = png_ptr->user_transform_depth;
  1.2104 +
  1.2105 +      if (info_ptr->channels < png_ptr->user_transform_channels)
  1.2106 +         info_ptr->channels = png_ptr->user_transform_channels;
  1.2107 +   }
  1.2108 +#endif
  1.2109 +
  1.2110 +   info_ptr->pixel_depth = (png_byte)(info_ptr->channels *
  1.2111 +       info_ptr->bit_depth);
  1.2112 +
  1.2113 +   info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, info_ptr->width);
  1.2114 +
  1.2115 +   /* Adding in 1.5.4: cache the above value in png_struct so that we can later
  1.2116 +    * check in png_rowbytes that the user buffer won't get overwritten.  Note
  1.2117 +    * that the field is not always set - if png_read_update_info isn't called
  1.2118 +    * the application has to either not do any transforms or get the calculation
  1.2119 +    * right itself.
  1.2120 +    */
  1.2121 +   png_ptr->info_rowbytes = info_ptr->rowbytes;
  1.2122 +
  1.2123 +#ifndef PNG_READ_EXPAND_SUPPORTED
  1.2124 +   if (png_ptr)
  1.2125 +      return;
  1.2126 +#endif
  1.2127 +}
  1.2128 +
  1.2129 +#ifdef PNG_READ_PACK_SUPPORTED
  1.2130 +/* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel,
  1.2131 + * without changing the actual values.  Thus, if you had a row with
  1.2132 + * a bit depth of 1, you would end up with bytes that only contained
  1.2133 + * the numbers 0 or 1.  If you would rather they contain 0 and 255, use
  1.2134 + * png_do_shift() after this.
  1.2135 + */
  1.2136 +static void
  1.2137 +png_do_unpack(png_row_infop row_info, png_bytep row)
  1.2138 +{
  1.2139 +   png_debug(1, "in png_do_unpack");
  1.2140 +
  1.2141 +   if (row_info->bit_depth < 8)
  1.2142 +   {
  1.2143 +      png_uint_32 i;
  1.2144 +      png_uint_32 row_width=row_info->width;
  1.2145 +
  1.2146 +      switch (row_info->bit_depth)
  1.2147 +      {
  1.2148 +         case 1:
  1.2149 +         {
  1.2150 +            png_bytep sp = row + (png_size_t)((row_width - 1) >> 3);
  1.2151 +            png_bytep dp = row + (png_size_t)row_width - 1;
  1.2152 +            png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07);
  1.2153 +            for (i = 0; i < row_width; i++)
  1.2154 +            {
  1.2155 +               *dp = (png_byte)((*sp >> shift) & 0x01);
  1.2156 +
  1.2157 +               if (shift == 7)
  1.2158 +               {
  1.2159 +                  shift = 0;
  1.2160 +                  sp--;
  1.2161 +               }
  1.2162 +
  1.2163 +               else
  1.2164 +                  shift++;
  1.2165 +
  1.2166 +               dp--;
  1.2167 +            }
  1.2168 +            break;
  1.2169 +         }
  1.2170 +
  1.2171 +         case 2:
  1.2172 +         {
  1.2173 +
  1.2174 +            png_bytep sp = row + (png_size_t)((row_width - 1) >> 2);
  1.2175 +            png_bytep dp = row + (png_size_t)row_width - 1;
  1.2176 +            png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
  1.2177 +            for (i = 0; i < row_width; i++)
  1.2178 +            {
  1.2179 +               *dp = (png_byte)((*sp >> shift) & 0x03);
  1.2180 +
  1.2181 +               if (shift == 6)
  1.2182 +               {
  1.2183 +                  shift = 0;
  1.2184 +                  sp--;
  1.2185 +               }
  1.2186 +
  1.2187 +               else
  1.2188 +                  shift += 2;
  1.2189 +
  1.2190 +               dp--;
  1.2191 +            }
  1.2192 +            break;
  1.2193 +         }
  1.2194 +
  1.2195 +         case 4:
  1.2196 +         {
  1.2197 +            png_bytep sp = row + (png_size_t)((row_width - 1) >> 1);
  1.2198 +            png_bytep dp = row + (png_size_t)row_width - 1;
  1.2199 +            png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
  1.2200 +            for (i = 0; i < row_width; i++)
  1.2201 +            {
  1.2202 +               *dp = (png_byte)((*sp >> shift) & 0x0f);
  1.2203 +
  1.2204 +               if (shift == 4)
  1.2205 +               {
  1.2206 +                  shift = 0;
  1.2207 +                  sp--;
  1.2208 +               }
  1.2209 +
  1.2210 +               else
  1.2211 +                  shift = 4;
  1.2212 +
  1.2213 +               dp--;
  1.2214 +            }
  1.2215 +            break;
  1.2216 +         }
  1.2217 +
  1.2218 +         default:
  1.2219 +            break;
  1.2220 +      }
  1.2221 +      row_info->bit_depth = 8;
  1.2222 +      row_info->pixel_depth = (png_byte)(8 * row_info->channels);
  1.2223 +      row_info->rowbytes = row_width * row_info->channels;
  1.2224 +   }
  1.2225 +}
  1.2226 +#endif
  1.2227 +
  1.2228 +#ifdef PNG_READ_SHIFT_SUPPORTED
  1.2229 +/* Reverse the effects of png_do_shift.  This routine merely shifts the
  1.2230 + * pixels back to their significant bits values.  Thus, if you have
  1.2231 + * a row of bit depth 8, but only 5 are significant, this will shift
  1.2232 + * the values back to 0 through 31.
  1.2233 + */
  1.2234 +static void
  1.2235 +png_do_unshift(png_row_infop row_info, png_bytep row,
  1.2236 +    png_const_color_8p sig_bits)
  1.2237 +{
  1.2238 +   int color_type;
  1.2239 +
  1.2240 +   png_debug(1, "in png_do_unshift");
  1.2241 +
  1.2242 +   /* The palette case has already been handled in the _init routine. */
  1.2243 +   color_type = row_info->color_type;
  1.2244 +
  1.2245 +   if (color_type != PNG_COLOR_TYPE_PALETTE)
  1.2246 +   {
  1.2247 +      int shift[4];
  1.2248 +      int channels = 0;
  1.2249 +      int bit_depth = row_info->bit_depth;
  1.2250 +
  1.2251 +      if (color_type & PNG_COLOR_MASK_COLOR)
  1.2252 +      {
  1.2253 +         shift[channels++] = bit_depth - sig_bits->red;
  1.2254 +         shift[channels++] = bit_depth - sig_bits->green;
  1.2255 +         shift[channels++] = bit_depth - sig_bits->blue;
  1.2256 +      }
  1.2257 +
  1.2258 +      else
  1.2259 +      {
  1.2260 +         shift[channels++] = bit_depth - sig_bits->gray;
  1.2261 +      }
  1.2262 +
  1.2263 +      if (color_type & PNG_COLOR_MASK_ALPHA)
  1.2264 +      {
  1.2265 +         shift[channels++] = bit_depth - sig_bits->alpha;
  1.2266 +      }
  1.2267 +
  1.2268 +      {
  1.2269 +         int c, have_shift;
  1.2270 +
  1.2271 +         for (c = have_shift = 0; c < channels; ++c)
  1.2272 +         {
  1.2273 +            /* A shift of more than the bit depth is an error condition but it
  1.2274 +             * gets ignored here.
  1.2275 +             */
  1.2276 +            if (shift[c] <= 0 || shift[c] >= bit_depth)
  1.2277 +               shift[c] = 0;
  1.2278 +
  1.2279 +            else
  1.2280 +               have_shift = 1;
  1.2281 +         }
  1.2282 +
  1.2283 +         if (!have_shift)
  1.2284 +            return;
  1.2285 +      }
  1.2286 +
  1.2287 +      switch (bit_depth)
  1.2288 +      {
  1.2289 +         default:
  1.2290 +         /* Must be 1bpp gray: should not be here! */
  1.2291 +            /* NOTREACHED */
  1.2292 +            break;
  1.2293 +
  1.2294 +         case 2:
  1.2295 +         /* Must be 2bpp gray */
  1.2296 +         /* assert(channels == 1 && shift[0] == 1) */
  1.2297 +         {
  1.2298 +            png_bytep bp = row;
  1.2299 +            png_bytep bp_end = bp + row_info->rowbytes;
  1.2300 +
  1.2301 +            while (bp < bp_end)
  1.2302 +            {
  1.2303 +               int b = (*bp >> 1) & 0x55;
  1.2304 +               *bp++ = (png_byte)b;
  1.2305 +            }
  1.2306 +            break;
  1.2307 +         }
  1.2308 +
  1.2309 +         case 4:
  1.2310 +         /* Must be 4bpp gray */
  1.2311 +         /* assert(channels == 1) */
  1.2312 +         {
  1.2313 +            png_bytep bp = row;
  1.2314 +            png_bytep bp_end = bp + row_info->rowbytes;
  1.2315 +            int gray_shift = shift[0];
  1.2316 +            int mask =  0xf >> gray_shift;
  1.2317 +
  1.2318 +            mask |= mask << 4;
  1.2319 +
  1.2320 +            while (bp < bp_end)
  1.2321 +            {
  1.2322 +               int b = (*bp >> gray_shift) & mask;
  1.2323 +               *bp++ = (png_byte)b;
  1.2324 +            }
  1.2325 +            break;
  1.2326 +         }
  1.2327 +
  1.2328 +         case 8:
  1.2329 +         /* Single byte components, G, GA, RGB, RGBA */
  1.2330 +         {
  1.2331 +            png_bytep bp = row;
  1.2332 +            png_bytep bp_end = bp + row_info->rowbytes;
  1.2333 +            int channel = 0;
  1.2334 +
  1.2335 +            while (bp < bp_end)
  1.2336 +            {
  1.2337 +               int b = *bp >> shift[channel];
  1.2338 +               if (++channel >= channels)
  1.2339 +                  channel = 0;
  1.2340 +               *bp++ = (png_byte)b;
  1.2341 +            }
  1.2342 +            break;
  1.2343 +         }
  1.2344 +
  1.2345 +#ifdef PNG_READ_16BIT_SUPPORTED
  1.2346 +         case 16:
  1.2347 +         /* Double byte components, G, GA, RGB, RGBA */
  1.2348 +         {
  1.2349 +            png_bytep bp = row;
  1.2350 +            png_bytep bp_end = bp + row_info->rowbytes;
  1.2351 +            int channel = 0;
  1.2352 +
  1.2353 +            while (bp < bp_end)
  1.2354 +            {
  1.2355 +               int value = (bp[0] << 8) + bp[1];
  1.2356 +
  1.2357 +               value >>= shift[channel];
  1.2358 +               if (++channel >= channels)
  1.2359 +                  channel = 0;
  1.2360 +               *bp++ = (png_byte)(value >> 8);
  1.2361 +               *bp++ = (png_byte)(value & 0xff);
  1.2362 +            }
  1.2363 +            break;
  1.2364 +         }
  1.2365 +#endif
  1.2366 +      }
  1.2367 +   }
  1.2368 +}
  1.2369 +#endif
  1.2370 +
  1.2371 +#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
  1.2372 +/* Scale rows of bit depth 16 down to 8 accurately */
  1.2373 +static void
  1.2374 +png_do_scale_16_to_8(png_row_infop row_info, png_bytep row)
  1.2375 +{
  1.2376 +   png_debug(1, "in png_do_scale_16_to_8");
  1.2377 +
  1.2378 +   if (row_info->bit_depth == 16)
  1.2379 +   {
  1.2380 +      png_bytep sp = row; /* source */
  1.2381 +      png_bytep dp = row; /* destination */
  1.2382 +      png_bytep ep = sp + row_info->rowbytes; /* end+1 */
  1.2383 +
  1.2384 +      while (sp < ep)
  1.2385 +      {
  1.2386 +         /* The input is an array of 16 bit components, these must be scaled to
  1.2387 +          * 8 bits each.  For a 16 bit value V the required value (from the PNG
  1.2388 +          * specification) is:
  1.2389 +          *
  1.2390 +          *    (V * 255) / 65535
  1.2391 +          *
  1.2392 +          * This reduces to round(V / 257), or floor((V + 128.5)/257)
  1.2393 +          *
  1.2394 +          * Represent V as the two byte value vhi.vlo.  Make a guess that the
  1.2395 +          * result is the top byte of V, vhi, then the correction to this value
  1.2396 +          * is:
  1.2397 +          *
  1.2398 +          *    error = floor(((V-vhi.vhi) + 128.5) / 257)
  1.2399 +          *          = floor(((vlo-vhi) + 128.5) / 257)
  1.2400 +          *
  1.2401 +          * This can be approximated using integer arithmetic (and a signed
  1.2402 +          * shift):
  1.2403 +          *
  1.2404 +          *    error = (vlo-vhi+128) >> 8;
  1.2405 +          *
  1.2406 +          * The approximate differs from the exact answer only when (vlo-vhi) is
  1.2407 +          * 128; it then gives a correction of +1 when the exact correction is
  1.2408 +          * 0.  This gives 128 errors.  The exact answer (correct for all 16 bit
  1.2409 +          * input values) is:
  1.2410 +          *
  1.2411 +          *    error = (vlo-vhi+128)*65535 >> 24;
  1.2412 +          *
  1.2413 +          * An alternative arithmetic calculation which also gives no errors is:
  1.2414 +          *
  1.2415 +          *    (V * 255 + 32895) >> 16
  1.2416 +          */
  1.2417 +
  1.2418 +         png_int_32 tmp = *sp++; /* must be signed! */
  1.2419 +         tmp += (((int)*sp++ - tmp + 128) * 65535) >> 24;
  1.2420 +         *dp++ = (png_byte)tmp;
  1.2421 +      }
  1.2422 +
  1.2423 +      row_info->bit_depth = 8;
  1.2424 +      row_info->pixel_depth = (png_byte)(8 * row_info->channels);
  1.2425 +      row_info->rowbytes = row_info->width * row_info->channels;
  1.2426 +   }
  1.2427 +}
  1.2428 +#endif
  1.2429 +
  1.2430 +#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
  1.2431 +static void
  1.2432 +/* Simply discard the low byte.  This was the default behavior prior
  1.2433 + * to libpng-1.5.4.
  1.2434 + */
  1.2435 +png_do_chop(png_row_infop row_info, png_bytep row)
  1.2436 +{
  1.2437 +   png_debug(1, "in png_do_chop");
  1.2438 +
  1.2439 +   if (row_info->bit_depth == 16)
  1.2440 +   {
  1.2441 +      png_bytep sp = row; /* source */
  1.2442 +      png_bytep dp = row; /* destination */
  1.2443 +      png_bytep ep = sp + row_info->rowbytes; /* end+1 */
  1.2444 +
  1.2445 +      while (sp < ep)
  1.2446 +      {
  1.2447 +         *dp++ = *sp;
  1.2448 +         sp += 2; /* skip low byte */
  1.2449 +      }
  1.2450 +
  1.2451 +      row_info->bit_depth = 8;
  1.2452 +      row_info->pixel_depth = (png_byte)(8 * row_info->channels);
  1.2453 +      row_info->rowbytes = row_info->width * row_info->channels;
  1.2454 +   }
  1.2455 +}
  1.2456 +#endif
  1.2457 +
  1.2458 +#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
  1.2459 +static void
  1.2460 +png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
  1.2461 +{
  1.2462 +   png_debug(1, "in png_do_read_swap_alpha");
  1.2463 +
  1.2464 +   {
  1.2465 +      png_uint_32 row_width = row_info->width;
  1.2466 +      if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
  1.2467 +      {
  1.2468 +         /* This converts from RGBA to ARGB */
  1.2469 +         if (row_info->bit_depth == 8)
  1.2470 +         {
  1.2471 +            png_bytep sp = row + row_info->rowbytes;
  1.2472 +            png_bytep dp = sp;
  1.2473 +            png_byte save;
  1.2474 +            png_uint_32 i;
  1.2475 +
  1.2476 +            for (i = 0; i < row_width; i++)
  1.2477 +            {
  1.2478 +               save = *(--sp);
  1.2479 +               *(--dp) = *(--sp);
  1.2480 +               *(--dp) = *(--sp);
  1.2481 +               *(--dp) = *(--sp);
  1.2482 +               *(--dp) = save;
  1.2483 +            }
  1.2484 +         }
  1.2485 +
  1.2486 +#ifdef PNG_READ_16BIT_SUPPORTED
  1.2487 +         /* This converts from RRGGBBAA to AARRGGBB */
  1.2488 +         else
  1.2489 +         {
  1.2490 +            png_bytep sp = row + row_info->rowbytes;
  1.2491 +            png_bytep dp = sp;
  1.2492 +            png_byte save[2];
  1.2493 +            png_uint_32 i;
  1.2494 +
  1.2495 +            for (i = 0; i < row_width; i++)
  1.2496 +            {
  1.2497 +               save[0] = *(--sp);
  1.2498 +               save[1] = *(--sp);
  1.2499 +               *(--dp) = *(--sp);
  1.2500 +               *(--dp) = *(--sp);
  1.2501 +               *(--dp) = *(--sp);
  1.2502 +               *(--dp) = *(--sp);
  1.2503 +               *(--dp) = *(--sp);
  1.2504 +               *(--dp) = *(--sp);
  1.2505 +               *(--dp) = save[0];
  1.2506 +               *(--dp) = save[1];
  1.2507 +            }
  1.2508 +         }
  1.2509 +#endif
  1.2510 +      }
  1.2511 +
  1.2512 +      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
  1.2513 +      {
  1.2514 +         /* This converts from GA to AG */
  1.2515 +         if (row_info->bit_depth == 8)
  1.2516 +         {
  1.2517 +            png_bytep sp = row + row_info->rowbytes;
  1.2518 +            png_bytep dp = sp;
  1.2519 +            png_byte save;
  1.2520 +            png_uint_32 i;
  1.2521 +
  1.2522 +            for (i = 0; i < row_width; i++)
  1.2523 +            {
  1.2524 +               save = *(--sp);
  1.2525 +               *(--dp) = *(--sp);
  1.2526 +               *(--dp) = save;
  1.2527 +            }
  1.2528 +         }
  1.2529 +
  1.2530 +#ifdef PNG_READ_16BIT_SUPPORTED
  1.2531 +         /* This converts from GGAA to AAGG */
  1.2532 +         else
  1.2533 +         {
  1.2534 +            png_bytep sp = row + row_info->rowbytes;
  1.2535 +            png_bytep dp = sp;
  1.2536 +            png_byte save[2];
  1.2537 +            png_uint_32 i;
  1.2538 +
  1.2539 +            for (i = 0; i < row_width; i++)
  1.2540 +            {
  1.2541 +               save[0] = *(--sp);
  1.2542 +               save[1] = *(--sp);
  1.2543 +               *(--dp) = *(--sp);
  1.2544 +               *(--dp) = *(--sp);
  1.2545 +               *(--dp) = save[0];
  1.2546 +               *(--dp) = save[1];
  1.2547 +            }
  1.2548 +         }
  1.2549 +#endif
  1.2550 +      }
  1.2551 +   }
  1.2552 +}
  1.2553 +#endif
  1.2554 +
  1.2555 +#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
  1.2556 +static void
  1.2557 +png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
  1.2558 +{
  1.2559 +   png_uint_32 row_width;
  1.2560 +   png_debug(1, "in png_do_read_invert_alpha");
  1.2561 +
  1.2562 +   row_width = row_info->width;
  1.2563 +   if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
  1.2564 +   {
  1.2565 +      if (row_info->bit_depth == 8)
  1.2566 +      {
  1.2567 +         /* This inverts the alpha channel in RGBA */
  1.2568 +         png_bytep sp = row + row_info->rowbytes;
  1.2569 +         png_bytep dp = sp;
  1.2570 +         png_uint_32 i;
  1.2571 +
  1.2572 +         for (i = 0; i < row_width; i++)
  1.2573 +         {
  1.2574 +            *(--dp) = (png_byte)(255 - *(--sp));
  1.2575 +
  1.2576 +/*          This does nothing:
  1.2577 +            *(--dp) = *(--sp);
  1.2578 +            *(--dp) = *(--sp);
  1.2579 +            *(--dp) = *(--sp);
  1.2580 +            We can replace it with:
  1.2581 +*/
  1.2582 +            sp-=3;
  1.2583 +            dp=sp;
  1.2584 +         }
  1.2585 +      }
  1.2586 +
  1.2587 +#ifdef PNG_READ_16BIT_SUPPORTED
  1.2588 +      /* This inverts the alpha channel in RRGGBBAA */
  1.2589 +      else
  1.2590 +      {
  1.2591 +         png_bytep sp = row + row_info->rowbytes;
  1.2592 +         png_bytep dp = sp;
  1.2593 +         png_uint_32 i;
  1.2594 +
  1.2595 +         for (i = 0; i < row_width; i++)
  1.2596 +         {
  1.2597 +            *(--dp) = (png_byte)(255 - *(--sp));
  1.2598 +            *(--dp) = (png_byte)(255 - *(--sp));
  1.2599 +
  1.2600 +/*          This does nothing:
  1.2601 +            *(--dp) = *(--sp);
  1.2602 +            *(--dp) = *(--sp);
  1.2603 +            *(--dp) = *(--sp);
  1.2604 +            *(--dp) = *(--sp);
  1.2605 +            *(--dp) = *(--sp);
  1.2606 +            *(--dp) = *(--sp);
  1.2607 +            We can replace it with:
  1.2608 +*/
  1.2609 +            sp-=6;
  1.2610 +            dp=sp;
  1.2611 +         }
  1.2612 +      }
  1.2613 +#endif
  1.2614 +   }
  1.2615 +   else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
  1.2616 +   {
  1.2617 +      if (row_info->bit_depth == 8)
  1.2618 +      {
  1.2619 +         /* This inverts the alpha channel in GA */
  1.2620 +         png_bytep sp = row + row_info->rowbytes;
  1.2621 +         png_bytep dp = sp;
  1.2622 +         png_uint_32 i;
  1.2623 +
  1.2624 +         for (i = 0; i < row_width; i++)
  1.2625 +         {
  1.2626 +            *(--dp) = (png_byte)(255 - *(--sp));
  1.2627 +            *(--dp) = *(--sp);
  1.2628 +         }
  1.2629 +      }
  1.2630 +
  1.2631 +#ifdef PNG_READ_16BIT_SUPPORTED
  1.2632 +      else
  1.2633 +      {
  1.2634 +         /* This inverts the alpha channel in GGAA */
  1.2635 +         png_bytep sp  = row + row_info->rowbytes;
  1.2636 +         png_bytep dp = sp;
  1.2637 +         png_uint_32 i;
  1.2638 +
  1.2639 +         for (i = 0; i < row_width; i++)
  1.2640 +         {
  1.2641 +            *(--dp) = (png_byte)(255 - *(--sp));
  1.2642 +            *(--dp) = (png_byte)(255 - *(--sp));
  1.2643 +/*
  1.2644 +            *(--dp) = *(--sp);
  1.2645 +            *(--dp) = *(--sp);
  1.2646 +*/
  1.2647 +            sp-=2;
  1.2648 +            dp=sp;
  1.2649 +         }
  1.2650 +      }
  1.2651 +#endif
  1.2652 +   }
  1.2653 +}
  1.2654 +#endif
  1.2655 +
  1.2656 +#ifdef PNG_READ_FILLER_SUPPORTED
  1.2657 +/* Add filler channel if we have RGB color */
  1.2658 +static void
  1.2659 +png_do_read_filler(png_row_infop row_info, png_bytep row,
  1.2660 +    png_uint_32 filler, png_uint_32 flags)
  1.2661 +{
  1.2662 +   png_uint_32 i;
  1.2663 +   png_uint_32 row_width = row_info->width;
  1.2664 +
  1.2665 +#ifdef PNG_READ_16BIT_SUPPORTED
  1.2666 +   png_byte hi_filler = (png_byte)((filler>>8) & 0xff);
  1.2667 +#endif
  1.2668 +   png_byte lo_filler = (png_byte)(filler & 0xff);
  1.2669 +
  1.2670 +   png_debug(1, "in png_do_read_filler");
  1.2671 +
  1.2672 +   if (
  1.2673 +       row_info->color_type == PNG_COLOR_TYPE_GRAY)
  1.2674 +   {
  1.2675 +      if (row_info->bit_depth == 8)
  1.2676 +      {
  1.2677 +         if (flags & PNG_FLAG_FILLER_AFTER)
  1.2678 +         {
  1.2679 +            /* This changes the data from G to GX */
  1.2680 +            png_bytep sp = row + (png_size_t)row_width;
  1.2681 +            png_bytep dp =  sp + (png_size_t)row_width;
  1.2682 +            for (i = 1; i < row_width; i++)
  1.2683 +            {
  1.2684 +               *(--dp) = lo_filler;
  1.2685 +               *(--dp) = *(--sp);
  1.2686 +            }
  1.2687 +            *(--dp) = lo_filler;
  1.2688 +            row_info->channels = 2;
  1.2689 +            row_info->pixel_depth = 16;
  1.2690 +            row_info->rowbytes = row_width * 2;
  1.2691 +         }
  1.2692 +
  1.2693 +         else
  1.2694 +         {
  1.2695 +            /* This changes the data from G to XG */
  1.2696 +            png_bytep sp = row + (png_size_t)row_width;
  1.2697 +            png_bytep dp = sp  + (png_size_t)row_width;
  1.2698 +            for (i = 0; i < row_width; i++)
  1.2699 +            {
  1.2700 +               *(--dp) = *(--sp);
  1.2701 +               *(--dp) = lo_filler;
  1.2702 +            }
  1.2703 +            row_info->channels = 2;
  1.2704 +            row_info->pixel_depth = 16;
  1.2705 +            row_info->rowbytes = row_width * 2;
  1.2706 +         }
  1.2707 +      }
  1.2708 +
  1.2709 +#ifdef PNG_READ_16BIT_SUPPORTED
  1.2710 +      else if (row_info->bit_depth == 16)
  1.2711 +      {
  1.2712 +         if (flags & PNG_FLAG_FILLER_AFTER)
  1.2713 +         {
  1.2714 +            /* This changes the data from GG to GGXX */
  1.2715 +            png_bytep sp = row + (png_size_t)row_width * 2;
  1.2716 +            png_bytep dp = sp  + (png_size_t)row_width * 2;
  1.2717 +            for (i = 1; i < row_width; i++)
  1.2718 +            {
  1.2719 +               *(--dp) = hi_filler;
  1.2720 +               *(--dp) = lo_filler;
  1.2721 +               *(--dp) = *(--sp);
  1.2722 +               *(--dp) = *(--sp);
  1.2723 +            }
  1.2724 +            *(--dp) = hi_filler;
  1.2725 +            *(--dp) = lo_filler;
  1.2726 +            row_info->channels = 2;
  1.2727 +            row_info->pixel_depth = 32;
  1.2728 +            row_info->rowbytes = row_width * 4;
  1.2729 +         }
  1.2730 +
  1.2731 +         else
  1.2732 +         {
  1.2733 +            /* This changes the data from GG to XXGG */
  1.2734 +            png_bytep sp = row + (png_size_t)row_width * 2;
  1.2735 +            png_bytep dp = sp  + (png_size_t)row_width * 2;
  1.2736 +            for (i = 0; i < row_width; i++)
  1.2737 +            {
  1.2738 +               *(--dp) = *(--sp);
  1.2739 +               *(--dp) = *(--sp);
  1.2740 +               *(--dp) = hi_filler;
  1.2741 +               *(--dp) = lo_filler;
  1.2742 +            }
  1.2743 +            row_info->channels = 2;
  1.2744 +            row_info->pixel_depth = 32;
  1.2745 +            row_info->rowbytes = row_width * 4;
  1.2746 +         }
  1.2747 +      }
  1.2748 +#endif
  1.2749 +   } /* COLOR_TYPE == GRAY */
  1.2750 +   else if (row_info->color_type == PNG_COLOR_TYPE_RGB)
  1.2751 +   {
  1.2752 +      if (row_info->bit_depth == 8)
  1.2753 +      {
  1.2754 +         if (flags & PNG_FLAG_FILLER_AFTER)
  1.2755 +         {
  1.2756 +            /* This changes the data from RGB to RGBX */
  1.2757 +            png_bytep sp = row + (png_size_t)row_width * 3;
  1.2758 +            png_bytep dp = sp  + (png_size_t)row_width;
  1.2759 +            for (i = 1; i < row_width; i++)
  1.2760 +            {
  1.2761 +               *(--dp) = lo_filler;
  1.2762 +               *(--dp) = *(--sp);
  1.2763 +               *(--dp) = *(--sp);
  1.2764 +               *(--dp) = *(--sp);
  1.2765 +            }
  1.2766 +            *(--dp) = lo_filler;
  1.2767 +            row_info->channels = 4;
  1.2768 +            row_info->pixel_depth = 32;
  1.2769 +            row_info->rowbytes = row_width * 4;
  1.2770 +         }
  1.2771 +
  1.2772 +         else
  1.2773 +         {
  1.2774 +            /* This changes the data from RGB to XRGB */
  1.2775 +            png_bytep sp = row + (png_size_t)row_width * 3;
  1.2776 +            png_bytep dp = sp + (png_size_t)row_width;
  1.2777 +            for (i = 0; i < row_width; i++)
  1.2778 +            {
  1.2779 +               *(--dp) = *(--sp);
  1.2780 +               *(--dp) = *(--sp);
  1.2781 +               *(--dp) = *(--sp);
  1.2782 +               *(--dp) = lo_filler;
  1.2783 +            }
  1.2784 +            row_info->channels = 4;
  1.2785 +            row_info->pixel_depth = 32;
  1.2786 +            row_info->rowbytes = row_width * 4;
  1.2787 +         }
  1.2788 +      }
  1.2789 +
  1.2790 +#ifdef PNG_READ_16BIT_SUPPORTED
  1.2791 +      else if (row_info->bit_depth == 16)
  1.2792 +      {
  1.2793 +         if (flags & PNG_FLAG_FILLER_AFTER)
  1.2794 +         {
  1.2795 +            /* This changes the data from RRGGBB to RRGGBBXX */
  1.2796 +            png_bytep sp = row + (png_size_t)row_width * 6;
  1.2797 +            png_bytep dp = sp  + (png_size_t)row_width * 2;
  1.2798 +            for (i = 1; i < row_width; i++)
  1.2799 +            {
  1.2800 +               *(--dp) = hi_filler;
  1.2801 +               *(--dp) = lo_filler;
  1.2802 +               *(--dp) = *(--sp);
  1.2803 +               *(--dp) = *(--sp);
  1.2804 +               *(--dp) = *(--sp);
  1.2805 +               *(--dp) = *(--sp);
  1.2806 +               *(--dp) = *(--sp);
  1.2807 +               *(--dp) = *(--sp);
  1.2808 +            }
  1.2809 +            *(--dp) = hi_filler;
  1.2810 +            *(--dp) = lo_filler;
  1.2811 +            row_info->channels = 4;
  1.2812 +            row_info->pixel_depth = 64;
  1.2813 +            row_info->rowbytes = row_width * 8;
  1.2814 +         }
  1.2815 +
  1.2816 +         else
  1.2817 +         {
  1.2818 +            /* This changes the data from RRGGBB to XXRRGGBB */
  1.2819 +            png_bytep sp = row + (png_size_t)row_width * 6;
  1.2820 +            png_bytep dp = sp  + (png_size_t)row_width * 2;
  1.2821 +            for (i = 0; i < row_width; i++)
  1.2822 +            {
  1.2823 +               *(--dp) = *(--sp);
  1.2824 +               *(--dp) = *(--sp);
  1.2825 +               *(--dp) = *(--sp);
  1.2826 +               *(--dp) = *(--sp);
  1.2827 +               *(--dp) = *(--sp);
  1.2828 +               *(--dp) = *(--sp);
  1.2829 +               *(--dp) = hi_filler;
  1.2830 +               *(--dp) = lo_filler;
  1.2831 +            }
  1.2832 +
  1.2833 +            row_info->channels = 4;
  1.2834 +            row_info->pixel_depth = 64;
  1.2835 +            row_info->rowbytes = row_width * 8;
  1.2836 +         }
  1.2837 +      }
  1.2838 +#endif
  1.2839 +   } /* COLOR_TYPE == RGB */
  1.2840 +}
  1.2841 +#endif
  1.2842 +
  1.2843 +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
  1.2844 +/* Expand grayscale files to RGB, with or without alpha */
  1.2845 +static void
  1.2846 +png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
  1.2847 +{
  1.2848 +   png_uint_32 i;
  1.2849 +   png_uint_32 row_width = row_info->width;
  1.2850 +
  1.2851 +   png_debug(1, "in png_do_gray_to_rgb");
  1.2852 +
  1.2853 +   if (row_info->bit_depth >= 8 &&
  1.2854 +       !(row_info->color_type & PNG_COLOR_MASK_COLOR))
  1.2855 +   {
  1.2856 +      if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
  1.2857 +      {
  1.2858 +         if (row_info->bit_depth == 8)
  1.2859 +         {
  1.2860 +            /* This changes G to RGB */
  1.2861 +            png_bytep sp = row + (png_size_t)row_width - 1;
  1.2862 +            png_bytep dp = sp  + (png_size_t)row_width * 2;
  1.2863 +            for (i = 0; i < row_width; i++)
  1.2864 +            {
  1.2865 +               *(dp--) = *sp;
  1.2866 +               *(dp--) = *sp;
  1.2867 +               *(dp--) = *(sp--);
  1.2868 +            }
  1.2869 +         }
  1.2870 +
  1.2871 +         else
  1.2872 +         {
  1.2873 +            /* This changes GG to RRGGBB */
  1.2874 +            png_bytep sp = row + (png_size_t)row_width * 2 - 1;
  1.2875 +            png_bytep dp = sp  + (png_size_t)row_width * 4;
  1.2876 +            for (i = 0; i < row_width; i++)
  1.2877 +            {
  1.2878 +               *(dp--) = *sp;
  1.2879 +               *(dp--) = *(sp - 1);
  1.2880 +               *(dp--) = *sp;
  1.2881 +               *(dp--) = *(sp - 1);
  1.2882 +               *(dp--) = *(sp--);
  1.2883 +               *(dp--) = *(sp--);
  1.2884 +            }
  1.2885 +         }
  1.2886 +      }
  1.2887 +
  1.2888 +      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
  1.2889 +      {
  1.2890 +         if (row_info->bit_depth == 8)
  1.2891 +         {
  1.2892 +            /* This changes GA to RGBA */
  1.2893 +            png_bytep sp = row + (png_size_t)row_width * 2 - 1;
  1.2894 +            png_bytep dp = sp  + (png_size_t)row_width * 2;
  1.2895 +            for (i = 0; i < row_width; i++)
  1.2896 +            {
  1.2897 +               *(dp--) = *(sp--);
  1.2898 +               *(dp--) = *sp;
  1.2899 +               *(dp--) = *sp;
  1.2900 +               *(dp--) = *(sp--);
  1.2901 +            }
  1.2902 +         }
  1.2903 +
  1.2904 +         else
  1.2905 +         {
  1.2906 +            /* This changes GGAA to RRGGBBAA */
  1.2907 +            png_bytep sp = row + (png_size_t)row_width * 4 - 1;
  1.2908 +            png_bytep dp = sp  + (png_size_t)row_width * 4;
  1.2909 +            for (i = 0; i < row_width; i++)
  1.2910 +            {
  1.2911 +               *(dp--) = *(sp--);
  1.2912 +               *(dp--) = *(sp--);
  1.2913 +               *(dp--) = *sp;
  1.2914 +               *(dp--) = *(sp - 1);
  1.2915 +               *(dp--) = *sp;
  1.2916 +               *(dp--) = *(sp - 1);
  1.2917 +               *(dp--) = *(sp--);
  1.2918 +               *(dp--) = *(sp--);
  1.2919 +            }
  1.2920 +         }
  1.2921 +      }
  1.2922 +      row_info->channels = (png_byte)(row_info->channels + 2);
  1.2923 +      row_info->color_type |= PNG_COLOR_MASK_COLOR;
  1.2924 +      row_info->pixel_depth = (png_byte)(row_info->channels *
  1.2925 +          row_info->bit_depth);
  1.2926 +      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
  1.2927 +   }
  1.2928 +}
  1.2929 +#endif
  1.2930 +
  1.2931 +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
  1.2932 +/* Reduce RGB files to grayscale, with or without alpha
  1.2933 + * using the equation given in Poynton's ColorFAQ of 1998-01-04 at
  1.2934 + * <http://www.inforamp.net/~poynton/>  (THIS LINK IS DEAD June 2008 but
  1.2935 + * versions dated 1998 through November 2002 have been archived at
  1.2936 + * http://web.archive.org/web/20000816232553/http://www.inforamp.net/
  1.2937 + * ~poynton/notes/colour_and_gamma/ColorFAQ.txt )
  1.2938 + * Charles Poynton poynton at poynton.com
  1.2939 + *
  1.2940 + *     Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
  1.2941 + *
  1.2942 + *  which can be expressed with integers as
  1.2943 + *
  1.2944 + *     Y = (6969 * R + 23434 * G + 2365 * B)/32768
  1.2945 + *
  1.2946 + * Poynton's current link (as of January 2003 through July 2011):
  1.2947 + * <http://www.poynton.com/notes/colour_and_gamma/>
  1.2948 + * has changed the numbers slightly:
  1.2949 + *
  1.2950 + *     Y = 0.2126*R + 0.7152*G + 0.0722*B
  1.2951 + *
  1.2952 + *  which can be expressed with integers as
  1.2953 + *
  1.2954 + *     Y = (6966 * R + 23436 * G + 2366 * B)/32768
  1.2955 + *
  1.2956 + *  Historically, however, libpng uses numbers derived from the ITU-R Rec 709
  1.2957 + *  end point chromaticities and the D65 white point.  Depending on the
  1.2958 + *  precision used for the D65 white point this produces a variety of different
  1.2959 + *  numbers, however if the four decimal place value used in ITU-R Rec 709 is
  1.2960 + *  used (0.3127,0.3290) the Y calculation would be:
  1.2961 + *
  1.2962 + *     Y = (6968 * R + 23435 * G + 2366 * B)/32768
  1.2963 + *
  1.2964 + *  While this is correct the rounding results in an overflow for white, because
  1.2965 + *  the sum of the rounded coefficients is 32769, not 32768.  Consequently
  1.2966 + *  libpng uses, instead, the closest non-overflowing approximation:
  1.2967 + *
  1.2968 + *     Y = (6968 * R + 23434 * G + 2366 * B)/32768
  1.2969 + *
  1.2970 + *  Starting with libpng-1.5.5, if the image being converted has a cHRM chunk
  1.2971 + *  (including an sRGB chunk) then the chromaticities are used to calculate the
  1.2972 + *  coefficients.  See the chunk handling in pngrutil.c for more information.
  1.2973 + *
  1.2974 + *  In all cases the calculation is to be done in a linear colorspace.  If no
  1.2975 + *  gamma information is available to correct the encoding of the original RGB
  1.2976 + *  values this results in an implicit assumption that the original PNG RGB
  1.2977 + *  values were linear.
  1.2978 + *
  1.2979 + *  Other integer coefficents can be used via png_set_rgb_to_gray().  Because
  1.2980 + *  the API takes just red and green coefficients the blue coefficient is
  1.2981 + *  calculated to make the sum 32768.  This will result in different rounding
  1.2982 + *  to that used above.
  1.2983 + */
  1.2984 +static int
  1.2985 +png_do_rgb_to_gray(png_structrp png_ptr, png_row_infop row_info, png_bytep row)
  1.2986 +
  1.2987 +{
  1.2988 +   int rgb_error = 0;
  1.2989 +
  1.2990 +   png_debug(1, "in png_do_rgb_to_gray");
  1.2991 +
  1.2992 +   if (!(row_info->color_type & PNG_COLOR_MASK_PALETTE) &&
  1.2993 +       (row_info->color_type & PNG_COLOR_MASK_COLOR))
  1.2994 +   {
  1.2995 +      PNG_CONST png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff;
  1.2996 +      PNG_CONST png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff;
  1.2997 +      PNG_CONST png_uint_32 bc = 32768 - rc - gc;
  1.2998 +      PNG_CONST png_uint_32 row_width = row_info->width;
  1.2999 +      PNG_CONST int have_alpha =
  1.3000 +         (row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0;
  1.3001 +
  1.3002 +      if (row_info->bit_depth == 8)
  1.3003 +      {
  1.3004 +#ifdef PNG_READ_GAMMA_SUPPORTED
  1.3005 +         /* Notice that gamma to/from 1 are not necessarily inverses (if
  1.3006 +          * there is an overall gamma correction).  Prior to 1.5.5 this code
  1.3007 +          * checked the linearized values for equality; this doesn't match
  1.3008 +          * the documentation, the original values must be checked.
  1.3009 +          */
  1.3010 +         if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
  1.3011 +         {
  1.3012 +            png_bytep sp = row;
  1.3013 +            png_bytep dp = row;
  1.3014 +            png_uint_32 i;
  1.3015 +
  1.3016 +            for (i = 0; i < row_width; i++)
  1.3017 +            {
  1.3018 +               png_byte red   = *(sp++);
  1.3019 +               png_byte green = *(sp++);
  1.3020 +               png_byte blue  = *(sp++);
  1.3021 +
  1.3022 +               if (red != green || red != blue)
  1.3023 +               {
  1.3024 +                  red = png_ptr->gamma_to_1[red];
  1.3025 +                  green = png_ptr->gamma_to_1[green];
  1.3026 +                  blue = png_ptr->gamma_to_1[blue];
  1.3027 +
  1.3028 +                  rgb_error |= 1;
  1.3029 +                  *(dp++) = png_ptr->gamma_from_1[
  1.3030 +                      (rc*red + gc*green + bc*blue + 16384)>>15];
  1.3031 +               }
  1.3032 +
  1.3033 +               else
  1.3034 +               {
  1.3035 +                  /* If there is no overall correction the table will not be
  1.3036 +                   * set.
  1.3037 +                   */
  1.3038 +                  if (png_ptr->gamma_table != NULL)
  1.3039 +                     red = png_ptr->gamma_table[red];
  1.3040 +
  1.3041 +                  *(dp++) = red;
  1.3042 +               }
  1.3043 +
  1.3044 +               if (have_alpha)
  1.3045 +                  *(dp++) = *(sp++);
  1.3046 +            }
  1.3047 +         }
  1.3048 +         else
  1.3049 +#endif
  1.3050 +         {
  1.3051 +            png_bytep sp = row;
  1.3052 +            png_bytep dp = row;
  1.3053 +            png_uint_32 i;
  1.3054 +
  1.3055 +            for (i = 0; i < row_width; i++)
  1.3056 +            {
  1.3057 +               png_byte red   = *(sp++);
  1.3058 +               png_byte green = *(sp++);
  1.3059 +               png_byte blue  = *(sp++);
  1.3060 +
  1.3061 +               if (red != green || red != blue)
  1.3062 +               {
  1.3063 +                  rgb_error |= 1;
  1.3064 +                  /* NOTE: this is the historical approach which simply
  1.3065 +                   * truncates the results.
  1.3066 +                   */
  1.3067 +                  *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15);
  1.3068 +               }
  1.3069 +
  1.3070 +               else
  1.3071 +                  *(dp++) = red;
  1.3072 +
  1.3073 +               if (have_alpha)
  1.3074 +                  *(dp++) = *(sp++);
  1.3075 +            }
  1.3076 +         }
  1.3077 +      }
  1.3078 +
  1.3079 +      else /* RGB bit_depth == 16 */
  1.3080 +      {
  1.3081 +#ifdef PNG_READ_GAMMA_SUPPORTED
  1.3082 +         if (png_ptr->gamma_16_to_1 != NULL && png_ptr->gamma_16_from_1 != NULL)
  1.3083 +         {
  1.3084 +            png_bytep sp = row;
  1.3085 +            png_bytep dp = row;
  1.3086 +            png_uint_32 i;
  1.3087 +
  1.3088 +            for (i = 0; i < row_width; i++)
  1.3089 +            {
  1.3090 +               png_uint_16 red, green, blue, w;
  1.3091 +
  1.3092 +               red   = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
  1.3093 +               green = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
  1.3094 +               blue  = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
  1.3095 +
  1.3096 +               if (red == green && red == blue)
  1.3097 +               {
  1.3098 +                  if (png_ptr->gamma_16_table != NULL)
  1.3099 +                     w = png_ptr->gamma_16_table[(red&0xff)
  1.3100 +                         >> png_ptr->gamma_shift][red>>8];
  1.3101 +
  1.3102 +                  else
  1.3103 +                     w = red;
  1.3104 +               }
  1.3105 +
  1.3106 +               else
  1.3107 +               {
  1.3108 +                  png_uint_16 red_1   = png_ptr->gamma_16_to_1[(red&0xff)
  1.3109 +                      >> png_ptr->gamma_shift][red>>8];
  1.3110 +                  png_uint_16 green_1 =
  1.3111 +                      png_ptr->gamma_16_to_1[(green&0xff) >>
  1.3112 +                      png_ptr->gamma_shift][green>>8];
  1.3113 +                  png_uint_16 blue_1  = png_ptr->gamma_16_to_1[(blue&0xff)
  1.3114 +                      >> png_ptr->gamma_shift][blue>>8];
  1.3115 +                  png_uint_16 gray16  = (png_uint_16)((rc*red_1 + gc*green_1
  1.3116 +                      + bc*blue_1 + 16384)>>15);
  1.3117 +                  w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
  1.3118 +                      png_ptr->gamma_shift][gray16 >> 8];
  1.3119 +                  rgb_error |= 1;
  1.3120 +               }
  1.3121 +
  1.3122 +               *(dp++) = (png_byte)((w>>8) & 0xff);
  1.3123 +               *(dp++) = (png_byte)(w & 0xff);
  1.3124 +
  1.3125 +               if (have_alpha)
  1.3126 +               {
  1.3127 +                  *(dp++) = *(sp++);
  1.3128 +                  *(dp++) = *(sp++);
  1.3129 +               }
  1.3130 +            }
  1.3131 +         }
  1.3132 +         else
  1.3133 +#endif
  1.3134 +         {
  1.3135 +            png_bytep sp = row;
  1.3136 +            png_bytep dp = row;
  1.3137 +            png_uint_32 i;
  1.3138 +
  1.3139 +            for (i = 0; i < row_width; i++)
  1.3140 +            {
  1.3141 +               png_uint_16 red, green, blue, gray16;
  1.3142 +
  1.3143 +               red   = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
  1.3144 +               green = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
  1.3145 +               blue  = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
  1.3146 +
  1.3147 +               if (red != green || red != blue)
  1.3148 +                  rgb_error |= 1;
  1.3149 +
  1.3150 +               /* From 1.5.5 in the 16 bit case do the accurate conversion even
  1.3151 +                * in the 'fast' case - this is because this is where the code
  1.3152 +                * ends up when handling linear 16 bit data.
  1.3153 +                */
  1.3154 +               gray16  = (png_uint_16)((rc*red + gc*green + bc*blue + 16384) >>
  1.3155 +                  15);
  1.3156 +               *(dp++) = (png_byte)((gray16>>8) & 0xff);
  1.3157 +               *(dp++) = (png_byte)(gray16 & 0xff);
  1.3158 +
  1.3159 +               if (have_alpha)
  1.3160 +               {
  1.3161 +                  *(dp++) = *(sp++);
  1.3162 +                  *(dp++) = *(sp++);
  1.3163 +               }
  1.3164 +            }
  1.3165 +         }
  1.3166 +      }
  1.3167 +
  1.3168 +      row_info->channels = (png_byte)(row_info->channels - 2);
  1.3169 +      row_info->color_type = (png_byte)(row_info->color_type &
  1.3170 +          ~PNG_COLOR_MASK_COLOR);
  1.3171 +      row_info->pixel_depth = (png_byte)(row_info->channels *
  1.3172 +          row_info->bit_depth);
  1.3173 +      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
  1.3174 +   }
  1.3175 +   return rgb_error;
  1.3176 +}
  1.3177 +#endif
  1.3178 +
  1.3179 +#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
  1.3180 +   defined(PNG_READ_ALPHA_MODE_SUPPORTED)
  1.3181 +/* Replace any alpha or transparency with the supplied background color.
  1.3182 + * "background" is already in the screen gamma, while "background_1" is
  1.3183 + * at a gamma of 1.0.  Paletted files have already been taken care of.
  1.3184 + */
  1.3185 +static void
  1.3186 +png_do_compose(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
  1.3187 +{
  1.3188 +#ifdef PNG_READ_GAMMA_SUPPORTED
  1.3189 +   png_const_bytep gamma_table = png_ptr->gamma_table;
  1.3190 +   png_const_bytep gamma_from_1 = png_ptr->gamma_from_1;
  1.3191 +   png_const_bytep gamma_to_1 = png_ptr->gamma_to_1;
  1.3192 +   png_const_uint_16pp gamma_16 = png_ptr->gamma_16_table;
  1.3193 +   png_const_uint_16pp gamma_16_from_1 = png_ptr->gamma_16_from_1;
  1.3194 +   png_const_uint_16pp gamma_16_to_1 = png_ptr->gamma_16_to_1;
  1.3195 +   int gamma_shift = png_ptr->gamma_shift;
  1.3196 +   int optimize = (png_ptr->flags & PNG_FLAG_OPTIMIZE_ALPHA) != 0;
  1.3197 +#endif
  1.3198 +
  1.3199 +   png_bytep sp;
  1.3200 +   png_uint_32 i;
  1.3201 +   png_uint_32 row_width = row_info->width;
  1.3202 +   int shift;
  1.3203 +
  1.3204 +   png_debug(1, "in png_do_compose");
  1.3205 +
  1.3206 +   {
  1.3207 +      switch (row_info->color_type)
  1.3208 +      {
  1.3209 +         case PNG_COLOR_TYPE_GRAY:
  1.3210 +         {
  1.3211 +            switch (row_info->bit_depth)
  1.3212 +            {
  1.3213 +               case 1:
  1.3214 +               {
  1.3215 +                  sp = row;
  1.3216 +                  shift = 7;
  1.3217 +                  for (i = 0; i < row_width; i++)
  1.3218 +                  {
  1.3219 +                     if ((png_uint_16)((*sp >> shift) & 0x01)
  1.3220 +                        == png_ptr->trans_color.gray)
  1.3221 +                     {
  1.3222 +                        unsigned int tmp = *sp & (0x7f7f >> (7 - shift));
  1.3223 +                        tmp |= png_ptr->background.gray << shift;
  1.3224 +                        *sp = (png_byte)(tmp & 0xff);
  1.3225 +                     }
  1.3226 +
  1.3227 +                     if (!shift)
  1.3228 +                     {
  1.3229 +                        shift = 7;
  1.3230 +                        sp++;
  1.3231 +                     }
  1.3232 +
  1.3233 +                     else
  1.3234 +                        shift--;
  1.3235 +                  }
  1.3236 +                  break;
  1.3237 +               }
  1.3238 +
  1.3239 +               case 2:
  1.3240 +               {
  1.3241 +#ifdef PNG_READ_GAMMA_SUPPORTED
  1.3242 +                  if (gamma_table != NULL)
  1.3243 +                  {
  1.3244 +                     sp = row;
  1.3245 +                     shift = 6;
  1.3246 +                     for (i = 0; i < row_width; i++)
  1.3247 +                     {
  1.3248 +                        if ((png_uint_16)((*sp >> shift) & 0x03)
  1.3249 +                            == png_ptr->trans_color.gray)
  1.3250 +                        {
  1.3251 +                           unsigned int tmp = *sp & (0x3f3f >> (6 - shift));
  1.3252 +                           tmp |= png_ptr->background.gray << shift;
  1.3253 +                           *sp = (png_byte)(tmp & 0xff);
  1.3254 +                        }
  1.3255 +
  1.3256 +                        else
  1.3257 +                        {
  1.3258 +                           unsigned int p = (*sp >> shift) & 0x03;
  1.3259 +                           unsigned int g = (gamma_table [p | (p << 2) |
  1.3260 +                               (p << 4) | (p << 6)] >> 6) & 0x03;
  1.3261 +                           unsigned int tmp = *sp & (0x3f3f >> (6 - shift));
  1.3262 +                           tmp |= g << shift;
  1.3263 +                           *sp = (png_byte)(tmp & 0xff);
  1.3264 +                        }
  1.3265 +
  1.3266 +                        if (!shift)
  1.3267 +                        {
  1.3268 +                           shift = 6;
  1.3269 +                           sp++;
  1.3270 +                        }
  1.3271 +
  1.3272 +                        else
  1.3273 +                           shift -= 2;
  1.3274 +                     }
  1.3275 +                  }
  1.3276 +
  1.3277 +                  else
  1.3278 +#endif
  1.3279 +                  {
  1.3280 +                     sp = row;
  1.3281 +                     shift = 6;
  1.3282 +                     for (i = 0; i < row_width; i++)
  1.3283 +                     {
  1.3284 +                        if ((png_uint_16)((*sp >> shift) & 0x03)
  1.3285 +                            == png_ptr->trans_color.gray)
  1.3286 +                        {
  1.3287 +                           unsigned int tmp = *sp & (0x3f3f >> (6 - shift));
  1.3288 +                           tmp |= png_ptr->background.gray << shift;
  1.3289 +                           *sp = (png_byte)(tmp & 0xff);
  1.3290 +                        }
  1.3291 +
  1.3292 +                        if (!shift)
  1.3293 +                        {
  1.3294 +                           shift = 6;
  1.3295 +                           sp++;
  1.3296 +                        }
  1.3297 +
  1.3298 +                        else
  1.3299 +                           shift -= 2;
  1.3300 +                     }
  1.3301 +                  }
  1.3302 +                  break;
  1.3303 +               }
  1.3304 +
  1.3305 +               case 4:
  1.3306 +               {
  1.3307 +#ifdef PNG_READ_GAMMA_SUPPORTED
  1.3308 +                  if (gamma_table != NULL)
  1.3309 +                  {
  1.3310 +                     sp = row;
  1.3311 +                     shift = 4;
  1.3312 +                     for (i = 0; i < row_width; i++)
  1.3313 +                     {
  1.3314 +                        if ((png_uint_16)((*sp >> shift) & 0x0f)
  1.3315 +                            == png_ptr->trans_color.gray)
  1.3316 +                        {
  1.3317 +                           unsigned int tmp = *sp & (0xf0f >> (4 - shift));
  1.3318 +                           tmp |= png_ptr->background.gray << shift;
  1.3319 +                           *sp = (png_byte)(tmp & 0xff);
  1.3320 +                        }
  1.3321 +
  1.3322 +                        else
  1.3323 +                        {
  1.3324 +                           unsigned int p = (*sp >> shift) & 0x0f;
  1.3325 +                           unsigned int g = (gamma_table[p | (p << 4)] >> 4) &
  1.3326 +                              0x0f;
  1.3327 +                           unsigned int tmp = *sp & (0xf0f >> (4 - shift));
  1.3328 +                           tmp |= g << shift;
  1.3329 +                           *sp = (png_byte)(tmp & 0xff);
  1.3330 +                        }
  1.3331 +
  1.3332 +                        if (!shift)
  1.3333 +                        {
  1.3334 +                           shift = 4;
  1.3335 +                           sp++;
  1.3336 +                        }
  1.3337 +
  1.3338 +                        else
  1.3339 +                           shift -= 4;
  1.3340 +                     }
  1.3341 +                  }
  1.3342 +
  1.3343 +                  else
  1.3344 +#endif
  1.3345 +                  {
  1.3346 +                     sp = row;
  1.3347 +                     shift = 4;
  1.3348 +                     for (i = 0; i < row_width; i++)
  1.3349 +                     {
  1.3350 +                        if ((png_uint_16)((*sp >> shift) & 0x0f)
  1.3351 +                            == png_ptr->trans_color.gray)
  1.3352 +                        {
  1.3353 +                           unsigned int tmp = *sp & (0xf0f >> (4 - shift));
  1.3354 +                           tmp |= png_ptr->background.gray << shift;
  1.3355 +                           *sp = (png_byte)(tmp & 0xff);
  1.3356 +                        }
  1.3357 +
  1.3358 +                        if (!shift)
  1.3359 +                        {
  1.3360 +                           shift = 4;
  1.3361 +                           sp++;
  1.3362 +                        }
  1.3363 +
  1.3364 +                        else
  1.3365 +                           shift -= 4;
  1.3366 +                     }
  1.3367 +                  }
  1.3368 +                  break;
  1.3369 +               }
  1.3370 +
  1.3371 +               case 8:
  1.3372 +               {
  1.3373 +#ifdef PNG_READ_GAMMA_SUPPORTED
  1.3374 +                  if (gamma_table != NULL)
  1.3375 +                  {
  1.3376 +                     sp = row;
  1.3377 +                     for (i = 0; i < row_width; i++, sp++)
  1.3378 +                     {
  1.3379 +                        if (*sp == png_ptr->trans_color.gray)
  1.3380 +                           *sp = (png_byte)png_ptr->background.gray;
  1.3381 +
  1.3382 +                        else
  1.3383 +                           *sp = gamma_table[*sp];
  1.3384 +                     }
  1.3385 +                  }
  1.3386 +                  else
  1.3387 +#endif
  1.3388 +                  {
  1.3389 +                     sp = row;
  1.3390 +                     for (i = 0; i < row_width; i++, sp++)
  1.3391 +                     {
  1.3392 +                        if (*sp == png_ptr->trans_color.gray)
  1.3393 +                           *sp = (png_byte)png_ptr->background.gray;
  1.3394 +                     }
  1.3395 +                  }
  1.3396 +                  break;
  1.3397 +               }
  1.3398 +
  1.3399 +               case 16:
  1.3400 +               {
  1.3401 +#ifdef PNG_READ_GAMMA_SUPPORTED
  1.3402 +                  if (gamma_16 != NULL)
  1.3403 +                  {
  1.3404 +                     sp = row;
  1.3405 +                     for (i = 0; i < row_width; i++, sp += 2)
  1.3406 +                     {
  1.3407 +                        png_uint_16 v;
  1.3408 +
  1.3409 +                        v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
  1.3410 +
  1.3411 +                        if (v == png_ptr->trans_color.gray)
  1.3412 +                        {
  1.3413 +                           /* Background is already in screen gamma */
  1.3414 +                           *sp = (png_byte)((png_ptr->background.gray >> 8)
  1.3415 +                                & 0xff);
  1.3416 +                           *(sp + 1) = (png_byte)(png_ptr->background.gray
  1.3417 +                                & 0xff);
  1.3418 +                        }
  1.3419 +
  1.3420 +                        else
  1.3421 +                        {
  1.3422 +                           v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
  1.3423 +                           *sp = (png_byte)((v >> 8) & 0xff);
  1.3424 +                           *(sp + 1) = (png_byte)(v & 0xff);
  1.3425 +                        }
  1.3426 +                     }
  1.3427 +                  }
  1.3428 +                  else
  1.3429 +#endif
  1.3430 +                  {
  1.3431 +                     sp = row;
  1.3432 +                     for (i = 0; i < row_width; i++, sp += 2)
  1.3433 +                     {
  1.3434 +                        png_uint_16 v;
  1.3435 +
  1.3436 +                        v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
  1.3437 +
  1.3438 +                        if (v == png_ptr->trans_color.gray)
  1.3439 +                        {
  1.3440 +                           *sp = (png_byte)((png_ptr->background.gray >> 8)
  1.3441 +                                & 0xff);
  1.3442 +                           *(sp + 1) = (png_byte)(png_ptr->background.gray
  1.3443 +                                & 0xff);
  1.3444 +                        }
  1.3445 +                     }
  1.3446 +                  }
  1.3447 +                  break;
  1.3448 +               }
  1.3449 +
  1.3450 +               default:
  1.3451 +                  break;
  1.3452 +            }
  1.3453 +            break;
  1.3454 +         }
  1.3455 +
  1.3456 +         case PNG_COLOR_TYPE_RGB:
  1.3457 +         {
  1.3458 +            if (row_info->bit_depth == 8)
  1.3459 +            {
  1.3460 +#ifdef PNG_READ_GAMMA_SUPPORTED
  1.3461 +               if (gamma_table != NULL)
  1.3462 +               {
  1.3463 +                  sp = row;
  1.3464 +                  for (i = 0; i < row_width; i++, sp += 3)
  1.3465 +                  {
  1.3466 +                     if (*sp == png_ptr->trans_color.red &&
  1.3467 +                         *(sp + 1) == png_ptr->trans_color.green &&
  1.3468 +                         *(sp + 2) == png_ptr->trans_color.blue)
  1.3469 +                     {
  1.3470 +                        *sp = (png_byte)png_ptr->background.red;
  1.3471 +                        *(sp + 1) = (png_byte)png_ptr->background.green;
  1.3472 +                        *(sp + 2) = (png_byte)png_ptr->background.blue;
  1.3473 +                     }
  1.3474 +
  1.3475 +                     else
  1.3476 +                     {
  1.3477 +                        *sp = gamma_table[*sp];
  1.3478 +                        *(sp + 1) = gamma_table[*(sp + 1)];
  1.3479 +                        *(sp + 2) = gamma_table[*(sp + 2)];
  1.3480 +                     }
  1.3481 +                  }
  1.3482 +               }
  1.3483 +               else
  1.3484 +#endif
  1.3485 +               {
  1.3486 +                  sp = row;
  1.3487 +                  for (i = 0; i < row_width; i++, sp += 3)
  1.3488 +                  {
  1.3489 +                     if (*sp == png_ptr->trans_color.red &&
  1.3490 +                         *(sp + 1) == png_ptr->trans_color.green &&
  1.3491 +                         *(sp + 2) == png_ptr->trans_color.blue)
  1.3492 +                     {
  1.3493 +                        *sp = (png_byte)png_ptr->background.red;
  1.3494 +                        *(sp + 1) = (png_byte)png_ptr->background.green;
  1.3495 +                        *(sp + 2) = (png_byte)png_ptr->background.blue;
  1.3496 +                     }
  1.3497 +                  }
  1.3498 +               }
  1.3499 +            }
  1.3500 +            else /* if (row_info->bit_depth == 16) */
  1.3501 +            {
  1.3502 +#ifdef PNG_READ_GAMMA_SUPPORTED
  1.3503 +               if (gamma_16 != NULL)
  1.3504 +               {
  1.3505 +                  sp = row;
  1.3506 +                  for (i = 0; i < row_width; i++, sp += 6)
  1.3507 +                  {
  1.3508 +                     png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
  1.3509 +
  1.3510 +                     png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
  1.3511 +                         + *(sp + 3));
  1.3512 +
  1.3513 +                     png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
  1.3514 +                         + *(sp + 5));
  1.3515 +
  1.3516 +                     if (r == png_ptr->trans_color.red &&
  1.3517 +                         g == png_ptr->trans_color.green &&
  1.3518 +                         b == png_ptr->trans_color.blue)
  1.3519 +                     {
  1.3520 +                        /* Background is already in screen gamma */
  1.3521 +                        *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
  1.3522 +                        *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
  1.3523 +                        *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
  1.3524 +                                & 0xff);
  1.3525 +                        *(sp + 3) = (png_byte)(png_ptr->background.green
  1.3526 +                                & 0xff);
  1.3527 +                        *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
  1.3528 +                                & 0xff);
  1.3529 +                        *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
  1.3530 +                     }
  1.3531 +
  1.3532 +                     else
  1.3533 +                     {
  1.3534 +                        png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
  1.3535 +                        *sp = (png_byte)((v >> 8) & 0xff);
  1.3536 +                        *(sp + 1) = (png_byte)(v & 0xff);
  1.3537 +
  1.3538 +                        v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
  1.3539 +                        *(sp + 2) = (png_byte)((v >> 8) & 0xff);
  1.3540 +                        *(sp + 3) = (png_byte)(v & 0xff);
  1.3541 +
  1.3542 +                        v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
  1.3543 +                        *(sp + 4) = (png_byte)((v >> 8) & 0xff);
  1.3544 +                        *(sp + 5) = (png_byte)(v & 0xff);
  1.3545 +                     }
  1.3546 +                  }
  1.3547 +               }
  1.3548 +
  1.3549 +               else
  1.3550 +#endif
  1.3551 +               {
  1.3552 +                  sp = row;
  1.3553 +                  for (i = 0; i < row_width; i++, sp += 6)
  1.3554 +                  {
  1.3555 +                     png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
  1.3556 +
  1.3557 +                     png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
  1.3558 +                         + *(sp + 3));
  1.3559 +
  1.3560 +                     png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
  1.3561 +                         + *(sp + 5));
  1.3562 +
  1.3563 +                     if (r == png_ptr->trans_color.red &&
  1.3564 +                         g == png_ptr->trans_color.green &&
  1.3565 +                         b == png_ptr->trans_color.blue)
  1.3566 +                     {
  1.3567 +                        *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
  1.3568 +                        *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
  1.3569 +                        *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
  1.3570 +                                & 0xff);
  1.3571 +                        *(sp + 3) = (png_byte)(png_ptr->background.green
  1.3572 +                                & 0xff);
  1.3573 +                        *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
  1.3574 +                                & 0xff);
  1.3575 +                        *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
  1.3576 +                     }
  1.3577 +                  }
  1.3578 +               }
  1.3579 +            }
  1.3580 +            break;
  1.3581 +         }
  1.3582 +
  1.3583 +         case PNG_COLOR_TYPE_GRAY_ALPHA:
  1.3584 +         {
  1.3585 +            if (row_info->bit_depth == 8)
  1.3586 +            {
  1.3587 +#ifdef PNG_READ_GAMMA_SUPPORTED
  1.3588 +               if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
  1.3589 +                   gamma_table != NULL)
  1.3590 +               {
  1.3591 +                  sp = row;
  1.3592 +                  for (i = 0; i < row_width; i++, sp += 2)
  1.3593 +                  {
  1.3594 +                     png_uint_16 a = *(sp + 1);
  1.3595 +
  1.3596 +                     if (a == 0xff)
  1.3597 +                        *sp = gamma_table[*sp];
  1.3598 +
  1.3599 +                     else if (a == 0)
  1.3600 +                     {
  1.3601 +                        /* Background is already in screen gamma */
  1.3602 +                        *sp = (png_byte)png_ptr->background.gray;
  1.3603 +                     }
  1.3604 +
  1.3605 +                     else
  1.3606 +                     {
  1.3607 +                        png_byte v, w;
  1.3608 +
  1.3609 +                        v = gamma_to_1[*sp];
  1.3610 +                        png_composite(w, v, a, png_ptr->background_1.gray);
  1.3611 +                        if (!optimize)
  1.3612 +                           w = gamma_from_1[w];
  1.3613 +                        *sp = w;
  1.3614 +                     }
  1.3615 +                  }
  1.3616 +               }
  1.3617 +               else
  1.3618 +#endif
  1.3619 +               {
  1.3620 +                  sp = row;
  1.3621 +                  for (i = 0; i < row_width; i++, sp += 2)
  1.3622 +                  {
  1.3623 +                     png_byte a = *(sp + 1);
  1.3624 +
  1.3625 +                     if (a == 0)
  1.3626 +                        *sp = (png_byte)png_ptr->background.gray;
  1.3627 +
  1.3628 +                     else if (a < 0xff)
  1.3629 +                        png_composite(*sp, *sp, a, png_ptr->background.gray);
  1.3630 +                  }
  1.3631 +               }
  1.3632 +            }
  1.3633 +            else /* if (png_ptr->bit_depth == 16) */
  1.3634 +            {
  1.3635 +#ifdef PNG_READ_GAMMA_SUPPORTED
  1.3636 +               if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
  1.3637 +                   gamma_16_to_1 != NULL)
  1.3638 +               {
  1.3639 +                  sp = row;
  1.3640 +                  for (i = 0; i < row_width; i++, sp += 4)
  1.3641 +                  {
  1.3642 +                     png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8)
  1.3643 +                         + *(sp + 3));
  1.3644 +
  1.3645 +                     if (a == (png_uint_16)0xffff)
  1.3646 +                     {
  1.3647 +                        png_uint_16 v;
  1.3648 +
  1.3649 +                        v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
  1.3650 +                        *sp = (png_byte)((v >> 8) & 0xff);
  1.3651 +                        *(sp + 1) = (png_byte)(v & 0xff);
  1.3652 +                     }
  1.3653 +
  1.3654 +                     else if (a == 0)
  1.3655 +                     {
  1.3656 +                        /* Background is already in screen gamma */
  1.3657 +                        *sp = (png_byte)((png_ptr->background.gray >> 8)
  1.3658 +                                & 0xff);
  1.3659 +                        *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
  1.3660 +                     }
  1.3661 +
  1.3662 +                     else
  1.3663 +                     {
  1.3664 +                        png_uint_16 g, v, w;
  1.3665 +
  1.3666 +                        g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
  1.3667 +                        png_composite_16(v, g, a, png_ptr->background_1.gray);
  1.3668 +                        if (optimize)
  1.3669 +                           w = v;
  1.3670 +                        else
  1.3671 +                           w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8];
  1.3672 +                        *sp = (png_byte)((w >> 8) & 0xff);
  1.3673 +                        *(sp + 1) = (png_byte)(w & 0xff);
  1.3674 +                     }
  1.3675 +                  }
  1.3676 +               }
  1.3677 +               else
  1.3678 +#endif
  1.3679 +               {
  1.3680 +                  sp = row;
  1.3681 +                  for (i = 0; i < row_width; i++, sp += 4)
  1.3682 +                  {
  1.3683 +                     png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8)
  1.3684 +                         + *(sp + 3));
  1.3685 +
  1.3686 +                     if (a == 0)
  1.3687 +                     {
  1.3688 +                        *sp = (png_byte)((png_ptr->background.gray >> 8)
  1.3689 +                                & 0xff);
  1.3690 +                        *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
  1.3691 +                     }
  1.3692 +
  1.3693 +                     else if (a < 0xffff)
  1.3694 +                     {
  1.3695 +                        png_uint_16 g, v;
  1.3696 +
  1.3697 +                        g = (png_uint_16)(((*sp) << 8) + *(sp + 1));
  1.3698 +                        png_composite_16(v, g, a, png_ptr->background.gray);
  1.3699 +                        *sp = (png_byte)((v >> 8) & 0xff);
  1.3700 +                        *(sp + 1) = (png_byte)(v & 0xff);
  1.3701 +                     }
  1.3702 +                  }
  1.3703 +               }
  1.3704 +            }
  1.3705 +            break;
  1.3706 +         }
  1.3707 +
  1.3708 +         case PNG_COLOR_TYPE_RGB_ALPHA:
  1.3709 +         {
  1.3710 +            if (row_info->bit_depth == 8)
  1.3711 +            {
  1.3712 +#ifdef PNG_READ_GAMMA_SUPPORTED
  1.3713 +               if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
  1.3714 +                   gamma_table != NULL)
  1.3715 +               {
  1.3716 +                  sp = row;
  1.3717 +                  for (i = 0; i < row_width; i++, sp += 4)
  1.3718 +                  {
  1.3719 +                     png_byte a = *(sp + 3);
  1.3720 +
  1.3721 +                     if (a == 0xff)
  1.3722 +                     {
  1.3723 +                        *sp = gamma_table[*sp];
  1.3724 +                        *(sp + 1) = gamma_table[*(sp + 1)];
  1.3725 +                        *(sp + 2) = gamma_table[*(sp + 2)];
  1.3726 +                     }
  1.3727 +
  1.3728 +                     else if (a == 0)
  1.3729 +                     {
  1.3730 +                        /* Background is already in screen gamma */
  1.3731 +                        *sp = (png_byte)png_ptr->background.red;
  1.3732 +                        *(sp + 1) = (png_byte)png_ptr->background.green;
  1.3733 +                        *(sp + 2) = (png_byte)png_ptr->background.blue;
  1.3734 +                     }
  1.3735 +
  1.3736 +                     else
  1.3737 +                     {
  1.3738 +                        png_byte v, w;
  1.3739 +
  1.3740 +                        v = gamma_to_1[*sp];
  1.3741 +                        png_composite(w, v, a, png_ptr->background_1.red);
  1.3742 +                        if (!optimize) w = gamma_from_1[w];
  1.3743 +                        *sp = w;
  1.3744 +
  1.3745 +                        v = gamma_to_1[*(sp + 1)];
  1.3746 +                        png_composite(w, v, a, png_ptr->background_1.green);
  1.3747 +                        if (!optimize) w = gamma_from_1[w];
  1.3748 +                        *(sp + 1) = w;
  1.3749 +
  1.3750 +                        v = gamma_to_1[*(sp + 2)];
  1.3751 +                        png_composite(w, v, a, png_ptr->background_1.blue);
  1.3752 +                        if (!optimize) w = gamma_from_1[w];
  1.3753 +                        *(sp + 2) = w;
  1.3754 +                     }
  1.3755 +                  }
  1.3756 +               }
  1.3757 +               else
  1.3758 +#endif
  1.3759 +               {
  1.3760 +                  sp = row;
  1.3761 +                  for (i = 0; i < row_width; i++, sp += 4)
  1.3762 +                  {
  1.3763 +                     png_byte a = *(sp + 3);
  1.3764 +
  1.3765 +                     if (a == 0)
  1.3766 +                     {
  1.3767 +                        *sp = (png_byte)png_ptr->background.red;
  1.3768 +                        *(sp + 1) = (png_byte)png_ptr->background.green;
  1.3769 +                        *(sp + 2) = (png_byte)png_ptr->background.blue;
  1.3770 +                     }
  1.3771 +
  1.3772 +                     else if (a < 0xff)
  1.3773 +                     {
  1.3774 +                        png_composite(*sp, *sp, a, png_ptr->background.red);
  1.3775 +
  1.3776 +                        png_composite(*(sp + 1), *(sp + 1), a,
  1.3777 +                            png_ptr->background.green);
  1.3778 +
  1.3779 +                        png_composite(*(sp + 2), *(sp + 2), a,
  1.3780 +                            png_ptr->background.blue);
  1.3781 +                     }
  1.3782 +                  }
  1.3783 +               }
  1.3784 +            }
  1.3785 +            else /* if (row_info->bit_depth == 16) */
  1.3786 +            {
  1.3787 +#ifdef PNG_READ_GAMMA_SUPPORTED
  1.3788 +               if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
  1.3789 +                   gamma_16_to_1 != NULL)
  1.3790 +               {
  1.3791 +                  sp = row;
  1.3792 +                  for (i = 0; i < row_width; i++, sp += 8)
  1.3793 +                  {
  1.3794 +                     png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
  1.3795 +                         << 8) + (png_uint_16)(*(sp + 7)));
  1.3796 +
  1.3797 +                     if (a == (png_uint_16)0xffff)
  1.3798 +                     {
  1.3799 +                        png_uint_16 v;
  1.3800 +
  1.3801 +                        v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
  1.3802 +                        *sp = (png_byte)((v >> 8) & 0xff);
  1.3803 +                        *(sp + 1) = (png_byte)(v & 0xff);
  1.3804 +
  1.3805 +                        v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
  1.3806 +                        *(sp + 2) = (png_byte)((v >> 8) & 0xff);
  1.3807 +                        *(sp + 3) = (png_byte)(v & 0xff);
  1.3808 +
  1.3809 +                        v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
  1.3810 +                        *(sp + 4) = (png_byte)((v >> 8) & 0xff);
  1.3811 +                        *(sp + 5) = (png_byte)(v & 0xff);
  1.3812 +                     }
  1.3813 +
  1.3814 +                     else if (a == 0)
  1.3815 +                     {
  1.3816 +                        /* Background is already in screen gamma */
  1.3817 +                        *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
  1.3818 +                        *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
  1.3819 +                        *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
  1.3820 +                                & 0xff);
  1.3821 +                        *(sp + 3) = (png_byte)(png_ptr->background.green
  1.3822 +                                & 0xff);
  1.3823 +                        *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
  1.3824 +                                & 0xff);
  1.3825 +                        *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
  1.3826 +                     }
  1.3827 +
  1.3828 +                     else
  1.3829 +                     {
  1.3830 +                        png_uint_16 v, w;
  1.3831 +
  1.3832 +                        v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
  1.3833 +                        png_composite_16(w, v, a, png_ptr->background_1.red);
  1.3834 +                        if (!optimize)
  1.3835 +                           w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >>
  1.3836 +                                8];
  1.3837 +                        *sp = (png_byte)((w >> 8) & 0xff);
  1.3838 +                        *(sp + 1) = (png_byte)(w & 0xff);
  1.3839 +
  1.3840 +                        v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)];
  1.3841 +                        png_composite_16(w, v, a, png_ptr->background_1.green);
  1.3842 +                        if (!optimize)
  1.3843 +                           w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >>
  1.3844 +                                8];
  1.3845 +
  1.3846 +                        *(sp + 2) = (png_byte)((w >> 8) & 0xff);
  1.3847 +                        *(sp + 3) = (png_byte)(w & 0xff);
  1.3848 +
  1.3849 +                        v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)];
  1.3850 +                        png_composite_16(w, v, a, png_ptr->background_1.blue);
  1.3851 +                        if (!optimize)
  1.3852 +                           w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >>
  1.3853 +                                8];
  1.3854 +
  1.3855 +                        *(sp + 4) = (png_byte)((w >> 8) & 0xff);
  1.3856 +                        *(sp + 5) = (png_byte)(w & 0xff);
  1.3857 +                     }
  1.3858 +                  }
  1.3859 +               }
  1.3860 +
  1.3861 +               else
  1.3862 +#endif
  1.3863 +               {
  1.3864 +                  sp = row;
  1.3865 +                  for (i = 0; i < row_width; i++, sp += 8)
  1.3866 +                  {
  1.3867 +                     png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
  1.3868 +                         << 8) + (png_uint_16)(*(sp + 7)));
  1.3869 +
  1.3870 +                     if (a == 0)
  1.3871 +                     {
  1.3872 +                        *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
  1.3873 +                        *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
  1.3874 +                        *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
  1.3875 +                                & 0xff);
  1.3876 +                        *(sp + 3) = (png_byte)(png_ptr->background.green
  1.3877 +                                & 0xff);
  1.3878 +                        *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
  1.3879 +                                & 0xff);
  1.3880 +                        *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
  1.3881 +                     }
  1.3882 +
  1.3883 +                     else if (a < 0xffff)
  1.3884 +                     {
  1.3885 +                        png_uint_16 v;
  1.3886 +
  1.3887 +                        png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
  1.3888 +                        png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
  1.3889 +                            + *(sp + 3));
  1.3890 +                        png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
  1.3891 +                            + *(sp + 5));
  1.3892 +
  1.3893 +                        png_composite_16(v, r, a, png_ptr->background.red);
  1.3894 +                        *sp = (png_byte)((v >> 8) & 0xff);
  1.3895 +                        *(sp + 1) = (png_byte)(v & 0xff);
  1.3896 +
  1.3897 +                        png_composite_16(v, g, a, png_ptr->background.green);
  1.3898 +                        *(sp + 2) = (png_byte)((v >> 8) & 0xff);
  1.3899 +                        *(sp + 3) = (png_byte)(v & 0xff);
  1.3900 +
  1.3901 +                        png_composite_16(v, b, a, png_ptr->background.blue);
  1.3902 +                        *(sp + 4) = (png_byte)((v >> 8) & 0xff);
  1.3903 +                        *(sp + 5) = (png_byte)(v & 0xff);
  1.3904 +                     }
  1.3905 +                  }
  1.3906 +               }
  1.3907 +            }
  1.3908 +            break;
  1.3909 +         }
  1.3910 +
  1.3911 +         default:
  1.3912 +            break;
  1.3913 +      }
  1.3914 +   }
  1.3915 +}
  1.3916 +#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_READ_ALPHA_MODE_SUPPORTED */
  1.3917 +
  1.3918 +#ifdef PNG_READ_GAMMA_SUPPORTED
  1.3919 +/* Gamma correct the image, avoiding the alpha channel.  Make sure
  1.3920 + * you do this after you deal with the transparency issue on grayscale
  1.3921 + * or RGB images. If your bit depth is 8, use gamma_table, if it
  1.3922 + * is 16, use gamma_16_table and gamma_shift.  Build these with
  1.3923 + * build_gamma_table().
  1.3924 + */
  1.3925 +static void
  1.3926 +png_do_gamma(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
  1.3927 +{
  1.3928 +   png_const_bytep gamma_table = png_ptr->gamma_table;
  1.3929 +   png_const_uint_16pp gamma_16_table = png_ptr->gamma_16_table;
  1.3930 +   int gamma_shift = png_ptr->gamma_shift;
  1.3931 +
  1.3932 +   png_bytep sp;
  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_gamma");
  1.3937 +
  1.3938 +   if (((row_info->bit_depth <= 8 && gamma_table != NULL) ||
  1.3939 +       (row_info->bit_depth == 16 && gamma_16_table != NULL)))
  1.3940 +   {
  1.3941 +      switch (row_info->color_type)
  1.3942 +      {
  1.3943 +         case PNG_COLOR_TYPE_RGB:
  1.3944 +         {
  1.3945 +            if (row_info->bit_depth == 8)
  1.3946 +            {
  1.3947 +               sp = row;
  1.3948 +               for (i = 0; i < row_width; i++)
  1.3949 +               {
  1.3950 +                  *sp = gamma_table[*sp];
  1.3951 +                  sp++;
  1.3952 +                  *sp = gamma_table[*sp];
  1.3953 +                  sp++;
  1.3954 +                  *sp = gamma_table[*sp];
  1.3955 +                  sp++;
  1.3956 +               }
  1.3957 +            }
  1.3958 +
  1.3959 +            else /* if (row_info->bit_depth == 16) */
  1.3960 +            {
  1.3961 +               sp = row;
  1.3962 +               for (i = 0; i < row_width; i++)
  1.3963 +               {
  1.3964 +                  png_uint_16 v;
  1.3965 +
  1.3966 +                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
  1.3967 +                  *sp = (png_byte)((v >> 8) & 0xff);
  1.3968 +                  *(sp + 1) = (png_byte)(v & 0xff);
  1.3969 +                  sp += 2;
  1.3970 +
  1.3971 +                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
  1.3972 +                  *sp = (png_byte)((v >> 8) & 0xff);
  1.3973 +                  *(sp + 1) = (png_byte)(v & 0xff);
  1.3974 +                  sp += 2;
  1.3975 +
  1.3976 +                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
  1.3977 +                  *sp = (png_byte)((v >> 8) & 0xff);
  1.3978 +                  *(sp + 1) = (png_byte)(v & 0xff);
  1.3979 +                  sp += 2;
  1.3980 +               }
  1.3981 +            }
  1.3982 +            break;
  1.3983 +         }
  1.3984 +
  1.3985 +         case PNG_COLOR_TYPE_RGB_ALPHA:
  1.3986 +         {
  1.3987 +            if (row_info->bit_depth == 8)
  1.3988 +            {
  1.3989 +               sp = row;
  1.3990 +               for (i = 0; i < row_width; i++)
  1.3991 +               {
  1.3992 +                  *sp = gamma_table[*sp];
  1.3993 +                  sp++;
  1.3994 +
  1.3995 +                  *sp = gamma_table[*sp];
  1.3996 +                  sp++;
  1.3997 +
  1.3998 +                  *sp = gamma_table[*sp];
  1.3999 +                  sp++;
  1.4000 +
  1.4001 +                  sp++;
  1.4002 +               }
  1.4003 +            }
  1.4004 +
  1.4005 +            else /* if (row_info->bit_depth == 16) */
  1.4006 +            {
  1.4007 +               sp = row;
  1.4008 +               for (i = 0; i < row_width; i++)
  1.4009 +               {
  1.4010 +                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
  1.4011 +                  *sp = (png_byte)((v >> 8) & 0xff);
  1.4012 +                  *(sp + 1) = (png_byte)(v & 0xff);
  1.4013 +                  sp += 2;
  1.4014 +
  1.4015 +                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
  1.4016 +                  *sp = (png_byte)((v >> 8) & 0xff);
  1.4017 +                  *(sp + 1) = (png_byte)(v & 0xff);
  1.4018 +                  sp += 2;
  1.4019 +
  1.4020 +                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
  1.4021 +                  *sp = (png_byte)((v >> 8) & 0xff);
  1.4022 +                  *(sp + 1) = (png_byte)(v & 0xff);
  1.4023 +                  sp += 4;
  1.4024 +               }
  1.4025 +            }
  1.4026 +            break;
  1.4027 +         }
  1.4028 +
  1.4029 +         case PNG_COLOR_TYPE_GRAY_ALPHA:
  1.4030 +         {
  1.4031 +            if (row_info->bit_depth == 8)
  1.4032 +            {
  1.4033 +               sp = row;
  1.4034 +               for (i = 0; i < row_width; i++)
  1.4035 +               {
  1.4036 +                  *sp = gamma_table[*sp];
  1.4037 +                  sp += 2;
  1.4038 +               }
  1.4039 +            }
  1.4040 +
  1.4041 +            else /* if (row_info->bit_depth == 16) */
  1.4042 +            {
  1.4043 +               sp = row;
  1.4044 +               for (i = 0; i < row_width; i++)
  1.4045 +               {
  1.4046 +                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
  1.4047 +                  *sp = (png_byte)((v >> 8) & 0xff);
  1.4048 +                  *(sp + 1) = (png_byte)(v & 0xff);
  1.4049 +                  sp += 4;
  1.4050 +               }
  1.4051 +            }
  1.4052 +            break;
  1.4053 +         }
  1.4054 +
  1.4055 +         case PNG_COLOR_TYPE_GRAY:
  1.4056 +         {
  1.4057 +            if (row_info->bit_depth == 2)
  1.4058 +            {
  1.4059 +               sp = row;
  1.4060 +               for (i = 0; i < row_width; i += 4)
  1.4061 +               {
  1.4062 +                  int a = *sp & 0xc0;
  1.4063 +                  int b = *sp & 0x30;
  1.4064 +                  int c = *sp & 0x0c;
  1.4065 +                  int d = *sp & 0x03;
  1.4066 +
  1.4067 +                  *sp = (png_byte)(
  1.4068 +                      ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)])   ) & 0xc0)|
  1.4069 +                      ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)|
  1.4070 +                      ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)|
  1.4071 +                      ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) ));
  1.4072 +                  sp++;
  1.4073 +               }
  1.4074 +            }
  1.4075 +
  1.4076 +            if (row_info->bit_depth == 4)
  1.4077 +            {
  1.4078 +               sp = row;
  1.4079 +               for (i = 0; i < row_width; i += 2)
  1.4080 +               {
  1.4081 +                  int msb = *sp & 0xf0;
  1.4082 +                  int lsb = *sp & 0x0f;
  1.4083 +
  1.4084 +                  *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0)
  1.4085 +                      | (((int)gamma_table[(lsb << 4) | lsb]) >> 4));
  1.4086 +                  sp++;
  1.4087 +               }
  1.4088 +            }
  1.4089 +
  1.4090 +            else if (row_info->bit_depth == 8)
  1.4091 +            {
  1.4092 +               sp = row;
  1.4093 +               for (i = 0; i < row_width; i++)
  1.4094 +               {
  1.4095 +                  *sp = gamma_table[*sp];
  1.4096 +                  sp++;
  1.4097 +               }
  1.4098 +            }
  1.4099 +
  1.4100 +            else if (row_info->bit_depth == 16)
  1.4101 +            {
  1.4102 +               sp = row;
  1.4103 +               for (i = 0; i < row_width; i++)
  1.4104 +               {
  1.4105 +                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
  1.4106 +                  *sp = (png_byte)((v >> 8) & 0xff);
  1.4107 +                  *(sp + 1) = (png_byte)(v & 0xff);
  1.4108 +                  sp += 2;
  1.4109 +               }
  1.4110 +            }
  1.4111 +            break;
  1.4112 +         }
  1.4113 +
  1.4114 +         default:
  1.4115 +            break;
  1.4116 +      }
  1.4117 +   }
  1.4118 +}
  1.4119 +#endif
  1.4120 +
  1.4121 +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
  1.4122 +/* Encode the alpha channel to the output gamma (the input channel is always
  1.4123 + * linear.)  Called only with color types that have an alpha channel.  Needs the
  1.4124 + * from_1 tables.
  1.4125 + */
  1.4126 +static void
  1.4127 +png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
  1.4128 +{
  1.4129 +   png_uint_32 row_width = row_info->width;
  1.4130 +
  1.4131 +   png_debug(1, "in png_do_encode_alpha");
  1.4132 +
  1.4133 +   if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
  1.4134 +   {
  1.4135 +      if (row_info->bit_depth == 8)
  1.4136 +      {
  1.4137 +         PNG_CONST png_bytep table = png_ptr->gamma_from_1;
  1.4138 +
  1.4139 +         if (table != NULL)
  1.4140 +         {
  1.4141 +            PNG_CONST int step =
  1.4142 +               (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 4 : 2;
  1.4143 +
  1.4144 +            /* The alpha channel is the last component: */
  1.4145 +            row += step - 1;
  1.4146 +
  1.4147 +            for (; row_width > 0; --row_width, row += step)
  1.4148 +               *row = table[*row];
  1.4149 +
  1.4150 +            return;
  1.4151 +         }
  1.4152 +      }
  1.4153 +
  1.4154 +      else if (row_info->bit_depth == 16)
  1.4155 +      {
  1.4156 +         PNG_CONST png_uint_16pp table = png_ptr->gamma_16_from_1;
  1.4157 +         PNG_CONST int gamma_shift = png_ptr->gamma_shift;
  1.4158 +
  1.4159 +         if (table != NULL)
  1.4160 +         {
  1.4161 +            PNG_CONST int step =
  1.4162 +               (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 8 : 4;
  1.4163 +
  1.4164 +            /* The alpha channel is the last component: */
  1.4165 +            row += step - 2;
  1.4166 +
  1.4167 +            for (; row_width > 0; --row_width, row += step)
  1.4168 +            {
  1.4169 +               png_uint_16 v;
  1.4170 +
  1.4171 +               v = table[*(row + 1) >> gamma_shift][*row];
  1.4172 +               *row = (png_byte)((v >> 8) & 0xff);
  1.4173 +               *(row + 1) = (png_byte)(v & 0xff);
  1.4174 +            }
  1.4175 +
  1.4176 +            return;
  1.4177 +         }
  1.4178 +      }
  1.4179 +   }
  1.4180 +
  1.4181 +   /* Only get to here if called with a weird row_info; no harm has been done,
  1.4182 +    * so just issue a warning.
  1.4183 +    */
  1.4184 +   png_warning(png_ptr, "png_do_encode_alpha: unexpected call");
  1.4185 +}
  1.4186 +#endif
  1.4187 +
  1.4188 +#ifdef PNG_READ_EXPAND_SUPPORTED
  1.4189 +/* Expands a palette row to an RGB or RGBA row depending
  1.4190 + * upon whether you supply trans and num_trans.
  1.4191 + */
  1.4192 +static void
  1.4193 +png_do_expand_palette(png_row_infop row_info, png_bytep row,
  1.4194 +   png_const_colorp palette, png_const_bytep trans_alpha, int num_trans)
  1.4195 +{
  1.4196 +   int shift, value;
  1.4197 +   png_bytep sp, dp;
  1.4198 +   png_uint_32 i;
  1.4199 +   png_uint_32 row_width=row_info->width;
  1.4200 +
  1.4201 +   png_debug(1, "in png_do_expand_palette");
  1.4202 +
  1.4203 +   if (row_info->color_type == PNG_COLOR_TYPE_PALETTE)
  1.4204 +   {
  1.4205 +      if (row_info->bit_depth < 8)
  1.4206 +      {
  1.4207 +         switch (row_info->bit_depth)
  1.4208 +         {
  1.4209 +            case 1:
  1.4210 +            {
  1.4211 +               sp = row + (png_size_t)((row_width - 1) >> 3);
  1.4212 +               dp = row + (png_size_t)row_width - 1;
  1.4213 +               shift = 7 - (int)((row_width + 7) & 0x07);
  1.4214 +               for (i = 0; i < row_width; i++)
  1.4215 +               {
  1.4216 +                  if ((*sp >> shift) & 0x01)
  1.4217 +                     *dp = 1;
  1.4218 +
  1.4219 +                  else
  1.4220 +                     *dp = 0;
  1.4221 +
  1.4222 +                  if (shift == 7)
  1.4223 +                  {
  1.4224 +                     shift = 0;
  1.4225 +                     sp--;
  1.4226 +                  }
  1.4227 +
  1.4228 +                  else
  1.4229 +                     shift++;
  1.4230 +
  1.4231 +                  dp--;
  1.4232 +               }
  1.4233 +               break;
  1.4234 +            }
  1.4235 +
  1.4236 +            case 2:
  1.4237 +            {
  1.4238 +               sp = row + (png_size_t)((row_width - 1) >> 2);
  1.4239 +               dp = row + (png_size_t)row_width - 1;
  1.4240 +               shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
  1.4241 +               for (i = 0; i < row_width; i++)
  1.4242 +               {
  1.4243 +                  value = (*sp >> shift) & 0x03;
  1.4244 +                  *dp = (png_byte)value;
  1.4245 +                  if (shift == 6)
  1.4246 +                  {
  1.4247 +                     shift = 0;
  1.4248 +                     sp--;
  1.4249 +                  }
  1.4250 +
  1.4251 +                  else
  1.4252 +                     shift += 2;
  1.4253 +
  1.4254 +                  dp--;
  1.4255 +               }
  1.4256 +               break;
  1.4257 +            }
  1.4258 +
  1.4259 +            case 4:
  1.4260 +            {
  1.4261 +               sp = row + (png_size_t)((row_width - 1) >> 1);
  1.4262 +               dp = row + (png_size_t)row_width - 1;
  1.4263 +               shift = (int)((row_width & 0x01) << 2);
  1.4264 +               for (i = 0; i < row_width; i++)
  1.4265 +               {
  1.4266 +                  value = (*sp >> shift) & 0x0f;
  1.4267 +                  *dp = (png_byte)value;
  1.4268 +                  if (shift == 4)
  1.4269 +                  {
  1.4270 +                     shift = 0;
  1.4271 +                     sp--;
  1.4272 +                  }
  1.4273 +
  1.4274 +                  else
  1.4275 +                     shift += 4;
  1.4276 +
  1.4277 +                  dp--;
  1.4278 +               }
  1.4279 +               break;
  1.4280 +            }
  1.4281 +
  1.4282 +            default:
  1.4283 +               break;
  1.4284 +         }
  1.4285 +         row_info->bit_depth = 8;
  1.4286 +         row_info->pixel_depth = 8;
  1.4287 +         row_info->rowbytes = row_width;
  1.4288 +      }
  1.4289 +
  1.4290 +      if (row_info->bit_depth == 8)
  1.4291 +      {
  1.4292 +         {
  1.4293 +            if (num_trans > 0)
  1.4294 +            {
  1.4295 +               sp = row + (png_size_t)row_width - 1;
  1.4296 +               dp = row + (png_size_t)(row_width << 2) - 1;
  1.4297 +
  1.4298 +               for (i = 0; i < row_width; i++)
  1.4299 +               {
  1.4300 +                  if ((int)(*sp) >= num_trans)
  1.4301 +                     *dp-- = 0xff;
  1.4302 +
  1.4303 +                  else
  1.4304 +                     *dp-- = trans_alpha[*sp];
  1.4305 +
  1.4306 +                  *dp-- = palette[*sp].blue;
  1.4307 +                  *dp-- = palette[*sp].green;
  1.4308 +                  *dp-- = palette[*sp].red;
  1.4309 +                  sp--;
  1.4310 +               }
  1.4311 +               row_info->bit_depth = 8;
  1.4312 +               row_info->pixel_depth = 32;
  1.4313 +               row_info->rowbytes = row_width * 4;
  1.4314 +               row_info->color_type = 6;
  1.4315 +               row_info->channels = 4;
  1.4316 +            }
  1.4317 +
  1.4318 +            else
  1.4319 +            {
  1.4320 +               sp = row + (png_size_t)row_width - 1;
  1.4321 +               dp = row + (png_size_t)(row_width * 3) - 1;
  1.4322 +
  1.4323 +               for (i = 0; i < row_width; i++)
  1.4324 +               {
  1.4325 +                  *dp-- = palette[*sp].blue;
  1.4326 +                  *dp-- = palette[*sp].green;
  1.4327 +                  *dp-- = palette[*sp].red;
  1.4328 +                  sp--;
  1.4329 +               }
  1.4330 +
  1.4331 +               row_info->bit_depth = 8;
  1.4332 +               row_info->pixel_depth = 24;
  1.4333 +               row_info->rowbytes = row_width * 3;
  1.4334 +               row_info->color_type = 2;
  1.4335 +               row_info->channels = 3;
  1.4336 +            }
  1.4337 +         }
  1.4338 +      }
  1.4339 +   }
  1.4340 +}
  1.4341 +
  1.4342 +/* If the bit depth < 8, it is expanded to 8.  Also, if the already
  1.4343 + * expanded transparency value is supplied, an alpha channel is built.
  1.4344 + */
  1.4345 +static void
  1.4346 +png_do_expand(png_row_infop row_info, png_bytep row,
  1.4347 +    png_const_color_16p trans_color)
  1.4348 +{
  1.4349 +   int shift, value;
  1.4350 +   png_bytep sp, dp;
  1.4351 +   png_uint_32 i;
  1.4352 +   png_uint_32 row_width=row_info->width;
  1.4353 +
  1.4354 +   png_debug(1, "in png_do_expand");
  1.4355 +
  1.4356 +   {
  1.4357 +      if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
  1.4358 +      {
  1.4359 +         unsigned int gray = trans_color ? trans_color->gray : 0;
  1.4360 +
  1.4361 +         if (row_info->bit_depth < 8)
  1.4362 +         {
  1.4363 +            switch (row_info->bit_depth)
  1.4364 +            {
  1.4365 +               case 1:
  1.4366 +               {
  1.4367 +                  gray = (gray & 0x01) * 0xff;
  1.4368 +                  sp = row + (png_size_t)((row_width - 1) >> 3);
  1.4369 +                  dp = row + (png_size_t)row_width - 1;
  1.4370 +                  shift = 7 - (int)((row_width + 7) & 0x07);
  1.4371 +                  for (i = 0; i < row_width; i++)
  1.4372 +                  {
  1.4373 +                     if ((*sp >> shift) & 0x01)
  1.4374 +                        *dp = 0xff;
  1.4375 +
  1.4376 +                     else
  1.4377 +                        *dp = 0;
  1.4378 +
  1.4379 +                     if (shift == 7)
  1.4380 +                     {
  1.4381 +                        shift = 0;
  1.4382 +                        sp--;
  1.4383 +                     }
  1.4384 +
  1.4385 +                     else
  1.4386 +                        shift++;
  1.4387 +
  1.4388 +                     dp--;
  1.4389 +                  }
  1.4390 +                  break;
  1.4391 +               }
  1.4392 +
  1.4393 +               case 2:
  1.4394 +               {
  1.4395 +                  gray = (gray & 0x03) * 0x55;
  1.4396 +                  sp = row + (png_size_t)((row_width - 1) >> 2);
  1.4397 +                  dp = row + (png_size_t)row_width - 1;
  1.4398 +                  shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
  1.4399 +                  for (i = 0; i < row_width; i++)
  1.4400 +                  {
  1.4401 +                     value = (*sp >> shift) & 0x03;
  1.4402 +                     *dp = (png_byte)(value | (value << 2) | (value << 4) |
  1.4403 +                        (value << 6));
  1.4404 +                     if (shift == 6)
  1.4405 +                     {
  1.4406 +                        shift = 0;
  1.4407 +                        sp--;
  1.4408 +                     }
  1.4409 +
  1.4410 +                     else
  1.4411 +                        shift += 2;
  1.4412 +
  1.4413 +                     dp--;
  1.4414 +                  }
  1.4415 +                  break;
  1.4416 +               }
  1.4417 +
  1.4418 +               case 4:
  1.4419 +               {
  1.4420 +                  gray = (gray & 0x0f) * 0x11;
  1.4421 +                  sp = row + (png_size_t)((row_width - 1) >> 1);
  1.4422 +                  dp = row + (png_size_t)row_width - 1;
  1.4423 +                  shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
  1.4424 +                  for (i = 0; i < row_width; i++)
  1.4425 +                  {
  1.4426 +                     value = (*sp >> shift) & 0x0f;
  1.4427 +                     *dp = (png_byte)(value | (value << 4));
  1.4428 +                     if (shift == 4)
  1.4429 +                     {
  1.4430 +                        shift = 0;
  1.4431 +                        sp--;
  1.4432 +                     }
  1.4433 +
  1.4434 +                     else
  1.4435 +                        shift = 4;
  1.4436 +
  1.4437 +                     dp--;
  1.4438 +                  }
  1.4439 +                  break;
  1.4440 +               }
  1.4441 +
  1.4442 +               default:
  1.4443 +                  break;
  1.4444 +            }
  1.4445 +
  1.4446 +            row_info->bit_depth = 8;
  1.4447 +            row_info->pixel_depth = 8;
  1.4448 +            row_info->rowbytes = row_width;
  1.4449 +         }
  1.4450 +
  1.4451 +         if (trans_color != NULL)
  1.4452 +         {
  1.4453 +            if (row_info->bit_depth == 8)
  1.4454 +            {
  1.4455 +               gray = gray & 0xff;
  1.4456 +               sp = row + (png_size_t)row_width - 1;
  1.4457 +               dp = row + (png_size_t)(row_width << 1) - 1;
  1.4458 +
  1.4459 +               for (i = 0; i < row_width; i++)
  1.4460 +               {
  1.4461 +                  if (*sp == gray)
  1.4462 +                     *dp-- = 0;
  1.4463 +
  1.4464 +                  else
  1.4465 +                     *dp-- = 0xff;
  1.4466 +
  1.4467 +                  *dp-- = *sp--;
  1.4468 +               }
  1.4469 +            }
  1.4470 +
  1.4471 +            else if (row_info->bit_depth == 16)
  1.4472 +            {
  1.4473 +               unsigned int gray_high = (gray >> 8) & 0xff;
  1.4474 +               unsigned int gray_low = gray & 0xff;
  1.4475 +               sp = row + row_info->rowbytes - 1;
  1.4476 +               dp = row + (row_info->rowbytes << 1) - 1;
  1.4477 +               for (i = 0; i < row_width; i++)
  1.4478 +               {
  1.4479 +                  if (*(sp - 1) == gray_high && *(sp) == gray_low)
  1.4480 +                  {
  1.4481 +                     *dp-- = 0;
  1.4482 +                     *dp-- = 0;
  1.4483 +                  }
  1.4484 +
  1.4485 +                  else
  1.4486 +                  {
  1.4487 +                     *dp-- = 0xff;
  1.4488 +                     *dp-- = 0xff;
  1.4489 +                  }
  1.4490 +
  1.4491 +                  *dp-- = *sp--;
  1.4492 +                  *dp-- = *sp--;
  1.4493 +               }
  1.4494 +            }
  1.4495 +
  1.4496 +            row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
  1.4497 +            row_info->channels = 2;
  1.4498 +            row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1);
  1.4499 +            row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
  1.4500 +               row_width);
  1.4501 +         }
  1.4502 +      }
  1.4503 +      else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_color)
  1.4504 +      {
  1.4505 +         if (row_info->bit_depth == 8)
  1.4506 +         {
  1.4507 +            png_byte red = (png_byte)(trans_color->red & 0xff);
  1.4508 +            png_byte green = (png_byte)(trans_color->green & 0xff);
  1.4509 +            png_byte blue = (png_byte)(trans_color->blue & 0xff);
  1.4510 +            sp = row + (png_size_t)row_info->rowbytes - 1;
  1.4511 +            dp = row + (png_size_t)(row_width << 2) - 1;
  1.4512 +            for (i = 0; i < row_width; i++)
  1.4513 +            {
  1.4514 +               if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue)
  1.4515 +                  *dp-- = 0;
  1.4516 +
  1.4517 +               else
  1.4518 +                  *dp-- = 0xff;
  1.4519 +
  1.4520 +               *dp-- = *sp--;
  1.4521 +               *dp-- = *sp--;
  1.4522 +               *dp-- = *sp--;
  1.4523 +            }
  1.4524 +         }
  1.4525 +         else if (row_info->bit_depth == 16)
  1.4526 +         {
  1.4527 +            png_byte red_high = (png_byte)((trans_color->red >> 8) & 0xff);
  1.4528 +            png_byte green_high = (png_byte)((trans_color->green >> 8) & 0xff);
  1.4529 +            png_byte blue_high = (png_byte)((trans_color->blue >> 8) & 0xff);
  1.4530 +            png_byte red_low = (png_byte)(trans_color->red & 0xff);
  1.4531 +            png_byte green_low = (png_byte)(trans_color->green & 0xff);
  1.4532 +            png_byte blue_low = (png_byte)(trans_color->blue & 0xff);
  1.4533 +            sp = row + row_info->rowbytes - 1;
  1.4534 +            dp = row + (png_size_t)(row_width << 3) - 1;
  1.4535 +            for (i = 0; i < row_width; i++)
  1.4536 +            {
  1.4537 +               if (*(sp - 5) == red_high &&
  1.4538 +                   *(sp - 4) == red_low &&
  1.4539 +                   *(sp - 3) == green_high &&
  1.4540 +                   *(sp - 2) == green_low &&
  1.4541 +                   *(sp - 1) == blue_high &&
  1.4542 +                   *(sp    ) == blue_low)
  1.4543 +               {
  1.4544 +                  *dp-- = 0;
  1.4545 +                  *dp-- = 0;
  1.4546 +               }
  1.4547 +
  1.4548 +               else
  1.4549 +               {
  1.4550 +                  *dp-- = 0xff;
  1.4551 +                  *dp-- = 0xff;
  1.4552 +               }
  1.4553 +
  1.4554 +               *dp-- = *sp--;
  1.4555 +               *dp-- = *sp--;
  1.4556 +               *dp-- = *sp--;
  1.4557 +               *dp-- = *sp--;
  1.4558 +               *dp-- = *sp--;
  1.4559 +               *dp-- = *sp--;
  1.4560 +            }
  1.4561 +         }
  1.4562 +         row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
  1.4563 +         row_info->channels = 4;
  1.4564 +         row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2);
  1.4565 +         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
  1.4566 +      }
  1.4567 +   }
  1.4568 +}
  1.4569 +#endif
  1.4570 +
  1.4571 +#ifdef PNG_READ_EXPAND_16_SUPPORTED
  1.4572 +/* If the bit depth is 8 and the color type is not a palette type expand the
  1.4573 + * whole row to 16 bits.  Has no effect otherwise.
  1.4574 + */
  1.4575 +static void
  1.4576 +png_do_expand_16(png_row_infop row_info, png_bytep row)
  1.4577 +{
  1.4578 +   if (row_info->bit_depth == 8 &&
  1.4579 +      row_info->color_type != PNG_COLOR_TYPE_PALETTE)
  1.4580 +   {
  1.4581 +      /* The row have a sequence of bytes containing [0..255] and we need
  1.4582 +       * to turn it into another row containing [0..65535], to do this we
  1.4583 +       * calculate:
  1.4584 +       *
  1.4585 +       *  (input / 255) * 65535
  1.4586 +       *
  1.4587 +       *  Which happens to be exactly input * 257 and this can be achieved
  1.4588 +       *  simply by byte replication in place (copying backwards).
  1.4589 +       */
  1.4590 +      png_byte *sp = row + row_info->rowbytes; /* source, last byte + 1 */
  1.4591 +      png_byte *dp = sp + row_info->rowbytes;  /* destination, end + 1 */
  1.4592 +      while (dp > sp)
  1.4593 +         dp[-2] = dp[-1] = *--sp, dp -= 2;
  1.4594 +
  1.4595 +      row_info->rowbytes *= 2;
  1.4596 +      row_info->bit_depth = 16;
  1.4597 +      row_info->pixel_depth = (png_byte)(row_info->channels * 16);
  1.4598 +   }
  1.4599 +}
  1.4600 +#endif
  1.4601 +
  1.4602 +#ifdef PNG_READ_QUANTIZE_SUPPORTED
  1.4603 +static void
  1.4604 +png_do_quantize(png_row_infop row_info, png_bytep row,
  1.4605 +    png_const_bytep palette_lookup, png_const_bytep quantize_lookup)
  1.4606 +{
  1.4607 +   png_bytep sp, dp;
  1.4608 +   png_uint_32 i;
  1.4609 +   png_uint_32 row_width=row_info->width;
  1.4610 +
  1.4611 +   png_debug(1, "in png_do_quantize");
  1.4612 +
  1.4613 +   if (row_info->bit_depth == 8)
  1.4614 +   {
  1.4615 +      if (row_info->color_type == PNG_COLOR_TYPE_RGB && palette_lookup)
  1.4616 +      {
  1.4617 +         int r, g, b, p;
  1.4618 +         sp = row;
  1.4619 +         dp = row;
  1.4620 +         for (i = 0; i < row_width; i++)
  1.4621 +         {
  1.4622 +            r = *sp++;
  1.4623 +            g = *sp++;
  1.4624 +            b = *sp++;
  1.4625 +
  1.4626 +            /* This looks real messy, but the compiler will reduce
  1.4627 +             * it down to a reasonable formula.  For example, with
  1.4628 +             * 5 bits per color, we get:
  1.4629 +             * p = (((r >> 3) & 0x1f) << 10) |
  1.4630 +             *    (((g >> 3) & 0x1f) << 5) |
  1.4631 +             *    ((b >> 3) & 0x1f);
  1.4632 +             */
  1.4633 +            p = (((r >> (8 - PNG_QUANTIZE_RED_BITS)) &
  1.4634 +                ((1 << PNG_QUANTIZE_RED_BITS) - 1)) <<
  1.4635 +                (PNG_QUANTIZE_GREEN_BITS + PNG_QUANTIZE_BLUE_BITS)) |
  1.4636 +                (((g >> (8 - PNG_QUANTIZE_GREEN_BITS)) &
  1.4637 +                ((1 << PNG_QUANTIZE_GREEN_BITS) - 1)) <<
  1.4638 +                (PNG_QUANTIZE_BLUE_BITS)) |
  1.4639 +                ((b >> (8 - PNG_QUANTIZE_BLUE_BITS)) &
  1.4640 +                ((1 << PNG_QUANTIZE_BLUE_BITS) - 1));
  1.4641 +
  1.4642 +            *dp++ = palette_lookup[p];
  1.4643 +         }
  1.4644 +
  1.4645 +         row_info->color_type = PNG_COLOR_TYPE_PALETTE;
  1.4646 +         row_info->channels = 1;
  1.4647 +         row_info->pixel_depth = row_info->bit_depth;
  1.4648 +         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
  1.4649 +      }
  1.4650 +
  1.4651 +      else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
  1.4652 +         palette_lookup != NULL)
  1.4653 +      {
  1.4654 +         int r, g, b, p;
  1.4655 +         sp = row;
  1.4656 +         dp = row;
  1.4657 +         for (i = 0; i < row_width; i++)
  1.4658 +         {
  1.4659 +            r = *sp++;
  1.4660 +            g = *sp++;
  1.4661 +            b = *sp++;
  1.4662 +            sp++;
  1.4663 +
  1.4664 +            p = (((r >> (8 - PNG_QUANTIZE_RED_BITS)) &
  1.4665 +                ((1 << PNG_QUANTIZE_RED_BITS) - 1)) <<
  1.4666 +                (PNG_QUANTIZE_GREEN_BITS + PNG_QUANTIZE_BLUE_BITS)) |
  1.4667 +                (((g >> (8 - PNG_QUANTIZE_GREEN_BITS)) &
  1.4668 +                ((1 << PNG_QUANTIZE_GREEN_BITS) - 1)) <<
  1.4669 +                (PNG_QUANTIZE_BLUE_BITS)) |
  1.4670 +                ((b >> (8 - PNG_QUANTIZE_BLUE_BITS)) &
  1.4671 +                ((1 << PNG_QUANTIZE_BLUE_BITS) - 1));
  1.4672 +
  1.4673 +            *dp++ = palette_lookup[p];
  1.4674 +         }
  1.4675 +
  1.4676 +         row_info->color_type = PNG_COLOR_TYPE_PALETTE;
  1.4677 +         row_info->channels = 1;
  1.4678 +         row_info->pixel_depth = row_info->bit_depth;
  1.4679 +         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
  1.4680 +      }
  1.4681 +
  1.4682 +      else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
  1.4683 +         quantize_lookup)
  1.4684 +      {
  1.4685 +         sp = row;
  1.4686 +
  1.4687 +         for (i = 0; i < row_width; i++, sp++)
  1.4688 +         {
  1.4689 +            *sp = quantize_lookup[*sp];
  1.4690 +         }
  1.4691 +      }
  1.4692 +   }
  1.4693 +}
  1.4694 +#endif /* PNG_READ_QUANTIZE_SUPPORTED */
  1.4695 +
  1.4696 +/* Transform the row.  The order of transformations is significant,
  1.4697 + * and is very touchy.  If you add a transformation, take care to
  1.4698 + * decide how it fits in with the other transformations here.
  1.4699 + */
  1.4700 +void /* PRIVATE */
  1.4701 +png_do_read_transformations(png_structrp png_ptr, png_row_infop row_info)
  1.4702 +{
  1.4703 +   png_debug(1, "in png_do_read_transformations");
  1.4704 +
  1.4705 +   if (png_ptr->row_buf == NULL)
  1.4706 +   {
  1.4707 +      /* Prior to 1.5.4 this output row/pass where the NULL pointer is, but this
  1.4708 +       * error is incredibly rare and incredibly easy to debug without this
  1.4709 +       * information.
  1.4710 +       */
  1.4711 +      png_error(png_ptr, "NULL row buffer");
  1.4712 +   }
  1.4713 +
  1.4714 +   /* The following is debugging; prior to 1.5.4 the code was never compiled in;
  1.4715 +    * in 1.5.4 PNG_FLAG_DETECT_UNINITIALIZED was added and the macro
  1.4716 +    * PNG_WARN_UNINITIALIZED_ROW removed.  In 1.6 the new flag is set only for
  1.4717 +    * all transformations, however in practice the ROW_INIT always gets done on
  1.4718 +    * demand, if necessary.
  1.4719 +    */
  1.4720 +   if ((png_ptr->flags & PNG_FLAG_DETECT_UNINITIALIZED) != 0 &&
  1.4721 +      !(png_ptr->flags & PNG_FLAG_ROW_INIT))
  1.4722 +   {
  1.4723 +      /* Application has failed to call either png_read_start_image() or
  1.4724 +       * png_read_update_info() after setting transforms that expand pixels.
  1.4725 +       * This check added to libpng-1.2.19 (but not enabled until 1.5.4).
  1.4726 +       */
  1.4727 +      png_error(png_ptr, "Uninitialized row");
  1.4728 +   }
  1.4729 +
  1.4730 +#ifdef PNG_READ_EXPAND_SUPPORTED
  1.4731 +   if (png_ptr->transformations & PNG_EXPAND)
  1.4732 +   {
  1.4733 +      if (row_info->color_type == PNG_COLOR_TYPE_PALETTE)
  1.4734 +      {
  1.4735 +         png_do_expand_palette(row_info, png_ptr->row_buf + 1,
  1.4736 +             png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans);
  1.4737 +      }
  1.4738 +
  1.4739 +      else
  1.4740 +      {
  1.4741 +         if (png_ptr->num_trans &&
  1.4742 +             (png_ptr->transformations & PNG_EXPAND_tRNS))
  1.4743 +            png_do_expand(row_info, png_ptr->row_buf + 1,
  1.4744 +                &(png_ptr->trans_color));
  1.4745 +
  1.4746 +         else
  1.4747 +            png_do_expand(row_info, png_ptr->row_buf + 1,
  1.4748 +                NULL);
  1.4749 +      }
  1.4750 +   }
  1.4751 +#endif
  1.4752 +
  1.4753 +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
  1.4754 +   if ((png_ptr->transformations & PNG_STRIP_ALPHA) &&
  1.4755 +      !(png_ptr->transformations & PNG_COMPOSE) &&
  1.4756 +      (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
  1.4757 +      row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
  1.4758 +      png_do_strip_channel(row_info, png_ptr->row_buf + 1,
  1.4759 +         0 /* at_start == false, because SWAP_ALPHA happens later */);
  1.4760 +#endif
  1.4761 +
  1.4762 +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
  1.4763 +   if (png_ptr->transformations & PNG_RGB_TO_GRAY)
  1.4764 +   {
  1.4765 +      int rgb_error =
  1.4766 +          png_do_rgb_to_gray(png_ptr, row_info,
  1.4767 +              png_ptr->row_buf + 1);
  1.4768 +
  1.4769 +      if (rgb_error)
  1.4770 +      {
  1.4771 +         png_ptr->rgb_to_gray_status=1;
  1.4772 +         if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
  1.4773 +             PNG_RGB_TO_GRAY_WARN)
  1.4774 +            png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel");
  1.4775 +
  1.4776 +         if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
  1.4777 +             PNG_RGB_TO_GRAY_ERR)
  1.4778 +            png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel");
  1.4779 +      }
  1.4780 +   }
  1.4781 +#endif
  1.4782 +
  1.4783 +/* From Andreas Dilger e-mail to png-implement, 26 March 1998:
  1.4784 + *
  1.4785 + *   In most cases, the "simple transparency" should be done prior to doing
  1.4786 + *   gray-to-RGB, or you will have to test 3x as many bytes to check if a
  1.4787 + *   pixel is transparent.  You would also need to make sure that the
  1.4788 + *   transparency information is upgraded to RGB.
  1.4789 + *
  1.4790 + *   To summarize, the current flow is:
  1.4791 + *   - Gray + simple transparency -> compare 1 or 2 gray bytes and composite
  1.4792 + *                                   with background "in place" if transparent,
  1.4793 + *                                   convert to RGB if necessary
  1.4794 + *   - Gray + alpha -> composite with gray background and remove alpha bytes,
  1.4795 + *                                   convert to RGB if necessary
  1.4796 + *
  1.4797 + *   To support RGB backgrounds for gray images we need:
  1.4798 + *   - Gray + simple transparency -> convert to RGB + simple transparency,
  1.4799 + *                                   compare 3 or 6 bytes and composite with
  1.4800 + *                                   background "in place" if transparent
  1.4801 + *                                   (3x compare/pixel compared to doing
  1.4802 + *                                   composite with gray bkgrnd)
  1.4803 + *   - Gray + alpha -> convert to RGB + alpha, composite with background and
  1.4804 + *                                   remove alpha bytes (3x float
  1.4805 + *                                   operations/pixel compared with composite
  1.4806 + *                                   on gray background)
  1.4807 + *
  1.4808 + *  Greg's change will do this.  The reason it wasn't done before is for
  1.4809 + *  performance, as this increases the per-pixel operations.  If we would check
  1.4810 + *  in advance if the background was gray or RGB, and position the gray-to-RGB
  1.4811 + *  transform appropriately, then it would save a lot of work/time.
  1.4812 + */
  1.4813 +
  1.4814 +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
  1.4815 +   /* If gray -> RGB, do so now only if background is non-gray; else do later
  1.4816 +    * for performance reasons
  1.4817 +    */
  1.4818 +   if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
  1.4819 +       !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
  1.4820 +      png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1);
  1.4821 +#endif
  1.4822 +
  1.4823 +#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
  1.4824 +   defined(PNG_READ_ALPHA_MODE_SUPPORTED)
  1.4825 +   if (png_ptr->transformations & PNG_COMPOSE)
  1.4826 +      png_do_compose(row_info, png_ptr->row_buf + 1, png_ptr);
  1.4827 +#endif
  1.4828 +
  1.4829 +#ifdef PNG_READ_GAMMA_SUPPORTED
  1.4830 +   if ((png_ptr->transformations & PNG_GAMMA) &&
  1.4831 +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
  1.4832 +      /* Because RGB_TO_GRAY does the gamma transform. */
  1.4833 +      !(png_ptr->transformations & PNG_RGB_TO_GRAY) &&
  1.4834 +#endif
  1.4835 +#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
  1.4836 +   defined(PNG_READ_ALPHA_MODE_SUPPORTED)
  1.4837 +      /* Because PNG_COMPOSE does the gamma transform if there is something to
  1.4838 +       * do (if there is an alpha channel or transparency.)
  1.4839 +       */
  1.4840 +       !((png_ptr->transformations & PNG_COMPOSE) &&
  1.4841 +       ((png_ptr->num_trans != 0) ||
  1.4842 +       (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) &&
  1.4843 +#endif
  1.4844 +      /* Because png_init_read_transformations transforms the palette, unless
  1.4845 +       * RGB_TO_GRAY will do the transform.
  1.4846 +       */
  1.4847 +       (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE))
  1.4848 +      png_do_gamma(row_info, png_ptr->row_buf + 1, png_ptr);
  1.4849 +#endif
  1.4850 +
  1.4851 +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
  1.4852 +   if ((png_ptr->transformations & PNG_STRIP_ALPHA) &&
  1.4853 +      (png_ptr->transformations & PNG_COMPOSE) &&
  1.4854 +      (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
  1.4855 +      row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
  1.4856 +      png_do_strip_channel(row_info, png_ptr->row_buf + 1,
  1.4857 +         0 /* at_start == false, because SWAP_ALPHA happens later */);
  1.4858 +#endif
  1.4859 +
  1.4860 +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
  1.4861 +   if ((png_ptr->transformations & PNG_ENCODE_ALPHA) &&
  1.4862 +      (row_info->color_type & PNG_COLOR_MASK_ALPHA))
  1.4863 +      png_do_encode_alpha(row_info, png_ptr->row_buf + 1, png_ptr);
  1.4864 +#endif
  1.4865 +
  1.4866 +#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
  1.4867 +   if (png_ptr->transformations & PNG_SCALE_16_TO_8)
  1.4868 +      png_do_scale_16_to_8(row_info, png_ptr->row_buf + 1);
  1.4869 +#endif
  1.4870 +
  1.4871 +#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
  1.4872 +   /* There is no harm in doing both of these because only one has any effect,
  1.4873 +    * by putting the 'scale' option first if the app asks for scale (either by
  1.4874 +    * calling the API or in a TRANSFORM flag) this is what happens.
  1.4875 +    */
  1.4876 +   if (png_ptr->transformations & PNG_16_TO_8)
  1.4877 +      png_do_chop(row_info, png_ptr->row_buf + 1);
  1.4878 +#endif
  1.4879 +
  1.4880 +#ifdef PNG_READ_QUANTIZE_SUPPORTED
  1.4881 +   if (png_ptr->transformations & PNG_QUANTIZE)
  1.4882 +   {
  1.4883 +      png_do_quantize(row_info, png_ptr->row_buf + 1,
  1.4884 +          png_ptr->palette_lookup, png_ptr->quantize_index);
  1.4885 +
  1.4886 +      if (row_info->rowbytes == 0)
  1.4887 +         png_error(png_ptr, "png_do_quantize returned rowbytes=0");
  1.4888 +   }
  1.4889 +#endif /* PNG_READ_QUANTIZE_SUPPORTED */
  1.4890 +
  1.4891 +#ifdef PNG_READ_EXPAND_16_SUPPORTED
  1.4892 +   /* Do the expansion now, after all the arithmetic has been done.  Notice
  1.4893 +    * that previous transformations can handle the PNG_EXPAND_16 flag if this
  1.4894 +    * is efficient (particularly true in the case of gamma correction, where
  1.4895 +    * better accuracy results faster!)
  1.4896 +    */
  1.4897 +   if (png_ptr->transformations & PNG_EXPAND_16)
  1.4898 +      png_do_expand_16(row_info, png_ptr->row_buf + 1);
  1.4899 +#endif
  1.4900 +
  1.4901 +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
  1.4902 +   /* NOTE: moved here in 1.5.4 (from much later in this list.) */
  1.4903 +   if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
  1.4904 +       (png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
  1.4905 +      png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1);
  1.4906 +#endif
  1.4907 +
  1.4908 +#ifdef PNG_READ_INVERT_SUPPORTED
  1.4909 +   if (png_ptr->transformations & PNG_INVERT_MONO)
  1.4910 +      png_do_invert(row_info, png_ptr->row_buf + 1);
  1.4911 +#endif
  1.4912 +
  1.4913 +#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
  1.4914 +   if (png_ptr->transformations & PNG_INVERT_ALPHA)
  1.4915 +      png_do_read_invert_alpha(row_info, png_ptr->row_buf + 1);
  1.4916 +#endif
  1.4917 +
  1.4918 +#ifdef PNG_READ_SHIFT_SUPPORTED
  1.4919 +   if (png_ptr->transformations & PNG_SHIFT)
  1.4920 +      png_do_unshift(row_info, png_ptr->row_buf + 1,
  1.4921 +          &(png_ptr->shift));
  1.4922 +#endif
  1.4923 +
  1.4924 +#ifdef PNG_READ_PACK_SUPPORTED
  1.4925 +   if (png_ptr->transformations & PNG_PACK)
  1.4926 +      png_do_unpack(row_info, png_ptr->row_buf + 1);
  1.4927 +#endif
  1.4928 +
  1.4929 +#ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED
  1.4930 +   /* Added at libpng-1.5.10 */
  1.4931 +   if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
  1.4932 +       png_ptr->num_palette_max >= 0)
  1.4933 +      png_do_check_palette_indexes(png_ptr, row_info);
  1.4934 +#endif
  1.4935 +
  1.4936 +#ifdef PNG_READ_BGR_SUPPORTED
  1.4937 +   if (png_ptr->transformations & PNG_BGR)
  1.4938 +      png_do_bgr(row_info, png_ptr->row_buf + 1);
  1.4939 +#endif
  1.4940 +
  1.4941 +#ifdef PNG_READ_PACKSWAP_SUPPORTED
  1.4942 +   if (png_ptr->transformations & PNG_PACKSWAP)
  1.4943 +      png_do_packswap(row_info, png_ptr->row_buf + 1);
  1.4944 +#endif
  1.4945 +
  1.4946 +#ifdef PNG_READ_FILLER_SUPPORTED
  1.4947 +   if (png_ptr->transformations & PNG_FILLER)
  1.4948 +      png_do_read_filler(row_info, png_ptr->row_buf + 1,
  1.4949 +          (png_uint_32)png_ptr->filler, png_ptr->flags);
  1.4950 +#endif
  1.4951 +
  1.4952 +#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
  1.4953 +   if (png_ptr->transformations & PNG_SWAP_ALPHA)
  1.4954 +      png_do_read_swap_alpha(row_info, png_ptr->row_buf + 1);
  1.4955 +#endif
  1.4956 +
  1.4957 +#ifdef PNG_READ_16BIT_SUPPORTED
  1.4958 +#ifdef PNG_READ_SWAP_SUPPORTED
  1.4959 +   if (png_ptr->transformations & PNG_SWAP_BYTES)
  1.4960 +      png_do_swap(row_info, png_ptr->row_buf + 1);
  1.4961 +#endif
  1.4962 +#endif
  1.4963 +
  1.4964 +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
  1.4965 +   if (png_ptr->transformations & PNG_USER_TRANSFORM)
  1.4966 +    {
  1.4967 +      if (png_ptr->read_user_transform_fn != NULL)
  1.4968 +         (*(png_ptr->read_user_transform_fn)) /* User read transform function */
  1.4969 +             (png_ptr,     /* png_ptr */
  1.4970 +             row_info,     /* row_info: */
  1.4971 +                /*  png_uint_32 width;       width of row */
  1.4972 +                /*  png_size_t rowbytes;     number of bytes in row */
  1.4973 +                /*  png_byte color_type;     color type of pixels */
  1.4974 +                /*  png_byte bit_depth;      bit depth of samples */
  1.4975 +                /*  png_byte channels;       number of channels (1-4) */
  1.4976 +                /*  png_byte pixel_depth;    bits per pixel (depth*channels) */
  1.4977 +             png_ptr->row_buf + 1);    /* start of pixel data for row */
  1.4978 +#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
  1.4979 +      if (png_ptr->user_transform_depth)
  1.4980 +         row_info->bit_depth = png_ptr->user_transform_depth;
  1.4981 +
  1.4982 +      if (png_ptr->user_transform_channels)
  1.4983 +         row_info->channels = png_ptr->user_transform_channels;
  1.4984 +#endif
  1.4985 +      row_info->pixel_depth = (png_byte)(row_info->bit_depth *
  1.4986 +          row_info->channels);
  1.4987 +
  1.4988 +      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_info->width);
  1.4989 +   }
  1.4990 +#endif
  1.4991 +}
  1.4992 +
  1.4993 +#endif /* PNG_READ_TRANSFORMS_SUPPORTED */
  1.4994 +#endif /* PNG_READ_SUPPORTED */

mercurial