jdk/src/java.desktop/share/native/libsplashscreen/libpng/pngrtran.c
changeset 25859 3317bb8137f4
parent 23903 3e78d4a02113
child 29913 95258013e132
equal deleted inserted replaced
25858:836adbf7a2cd 25859:3317bb8137f4
       
     1 /*
       
     2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     3  *
       
     4  * This code is free software; you can redistribute it and/or modify it
       
     5  * under the terms of the GNU General Public License version 2 only, as
       
     6  * published by the Free Software Foundation.  Oracle designates this
       
     7  * particular file as subject to the "Classpath" exception as provided
       
     8  * by Oracle in the LICENSE file that accompanied this code.
       
     9  *
       
    10  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    13  * version 2 for more details (a copy is included in the LICENSE file that
       
    14  * accompanied this code).
       
    15  *
       
    16  * You should have received a copy of the GNU General Public License version
       
    17  * 2 along with this work; if not, write to the Free Software Foundation,
       
    18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    19  *
       
    20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    21  * or visit www.oracle.com if you need additional information or have any
       
    22  * questions.
       
    23  */
       
    24 
       
    25 /* pngrtran.c - transforms the data in a row for PNG readers
       
    26  *
       
    27  * This file is available under and governed by the GNU General Public
       
    28  * License version 2 only, as published by the Free Software Foundation.
       
    29  * However, the following notice accompanied the original version of this
       
    30  * file and, per its terms, should not be removed:
       
    31  *
       
    32  * Last changed in libpng 1.5.4 [July 7, 2011]
       
    33  * Copyright (c) 1998-2011 Glenn Randers-Pehrson
       
    34  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
       
    35  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
       
    36  *
       
    37  * This code is released under the libpng license.
       
    38  * For conditions of distribution and use, see the disclaimer
       
    39  * and license in png.h
       
    40  *
       
    41  * This file contains functions optionally called by an application
       
    42  * in order to tell libpng how to handle data when reading a PNG.
       
    43  * Transformations that are used in both reading and writing are
       
    44  * in pngtrans.c.
       
    45  */
       
    46 
       
    47 #include "pngpriv.h"
       
    48 
       
    49 #ifdef PNG_READ_SUPPORTED
       
    50 
       
    51 /* Set the action on getting a CRC error for an ancillary or critical chunk. */
       
    52 void PNGAPI
       
    53 png_set_crc_action(png_structp png_ptr, int crit_action, int ancil_action)
       
    54 {
       
    55    png_debug(1, "in png_set_crc_action");
       
    56 
       
    57    if (png_ptr == NULL)
       
    58       return;
       
    59 
       
    60    /* Tell libpng how we react to CRC errors in critical chunks */
       
    61    switch (crit_action)
       
    62    {
       
    63       case PNG_CRC_NO_CHANGE:                        /* Leave setting as is */
       
    64          break;
       
    65 
       
    66       case PNG_CRC_WARN_USE:                               /* Warn/use data */
       
    67          png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
       
    68          png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE;
       
    69          break;
       
    70 
       
    71       case PNG_CRC_QUIET_USE:                             /* Quiet/use data */
       
    72          png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
       
    73          png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE |
       
    74                            PNG_FLAG_CRC_CRITICAL_IGNORE;
       
    75          break;
       
    76 
       
    77       case PNG_CRC_WARN_DISCARD:    /* Not a valid action for critical data */
       
    78          png_warning(png_ptr,
       
    79             "Can't discard critical data on CRC error");
       
    80       case PNG_CRC_ERROR_QUIT:                                /* Error/quit */
       
    81 
       
    82       case PNG_CRC_DEFAULT:
       
    83       default:
       
    84          png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
       
    85          break;
       
    86    }
       
    87 
       
    88    /* Tell libpng how we react to CRC errors in ancillary chunks */
       
    89    switch (ancil_action)
       
    90    {
       
    91       case PNG_CRC_NO_CHANGE:                       /* Leave setting as is */
       
    92          break;
       
    93 
       
    94       case PNG_CRC_WARN_USE:                              /* Warn/use data */
       
    95          png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
       
    96          png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE;
       
    97          break;
       
    98 
       
    99       case PNG_CRC_QUIET_USE:                            /* Quiet/use data */
       
   100          png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
       
   101          png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE |
       
   102                            PNG_FLAG_CRC_ANCILLARY_NOWARN;
       
   103          break;
       
   104 
       
   105       case PNG_CRC_ERROR_QUIT:                               /* Error/quit */
       
   106          png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
       
   107          png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN;
       
   108          break;
       
   109 
       
   110       case PNG_CRC_WARN_DISCARD:                      /* Warn/discard data */
       
   111 
       
   112       case PNG_CRC_DEFAULT:
       
   113       default:
       
   114          png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
       
   115          break;
       
   116    }
       
   117 }
       
   118 
       
   119 #ifdef PNG_READ_BACKGROUND_SUPPORTED
       
   120 /* Handle alpha and tRNS via a background color */
       
   121 void PNGFAPI
       
   122 png_set_background_fixed(png_structp png_ptr,
       
   123     png_const_color_16p background_color, int background_gamma_code,
       
   124     int need_expand, png_fixed_point background_gamma)
       
   125 {
       
   126    png_debug(1, "in png_set_background_fixed");
       
   127 
       
   128    if (png_ptr == NULL)
       
   129       return;
       
   130 
       
   131    if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN)
       
   132    {
       
   133       png_warning(png_ptr, "Application must supply a known background gamma");
       
   134       return;
       
   135    }
       
   136 
       
   137    png_ptr->transformations |= PNG_COMPOSE | PNG_STRIP_ALPHA;
       
   138    png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
       
   139    png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
       
   140 
       
   141    png_memcpy(&(png_ptr->background), background_color,
       
   142       png_sizeof(png_color_16));
       
   143    png_ptr->background_gamma = background_gamma;
       
   144    png_ptr->background_gamma_type = (png_byte)(background_gamma_code);
       
   145    if (need_expand)
       
   146       png_ptr->transformations |= PNG_BACKGROUND_EXPAND;
       
   147    else
       
   148       png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND;
       
   149 }
       
   150 
       
   151 #  ifdef PNG_FLOATING_POINT_SUPPORTED
       
   152 void PNGAPI
       
   153 png_set_background(png_structp png_ptr,
       
   154     png_const_color_16p background_color, int background_gamma_code,
       
   155     int need_expand, double background_gamma)
       
   156 {
       
   157    png_set_background_fixed(png_ptr, background_color, background_gamma_code,
       
   158       need_expand, png_fixed(png_ptr, background_gamma, "png_set_background"));
       
   159 }
       
   160 #  endif  /* FLOATING_POINT */
       
   161 #endif /* READ_BACKGROUND */
       
   162 
       
   163 /* Scale 16-bit depth files to 8-bit depth.  If both of these are set then the
       
   164  * one that pngrtran does first (scale) happens.  This is necessary to allow the
       
   165  * TRANSFORM and API behavior to be somewhat consistent, and it's simpler.
       
   166  */
       
   167 #ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
       
   168 void PNGAPI
       
   169 png_set_scale_16(png_structp png_ptr)
       
   170 {
       
   171    png_debug(1, "in png_set_scale_16");
       
   172 
       
   173    if (png_ptr == NULL)
       
   174       return;
       
   175 
       
   176    png_ptr->transformations |= PNG_SCALE_16_TO_8;
       
   177 }
       
   178 #endif
       
   179 
       
   180 #ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
       
   181 /* Chop 16-bit depth files to 8-bit depth */
       
   182 void PNGAPI
       
   183 png_set_strip_16(png_structp png_ptr)
       
   184 {
       
   185    png_debug(1, "in png_set_strip_16");
       
   186 
       
   187    if (png_ptr == NULL)
       
   188       return;
       
   189 
       
   190    png_ptr->transformations |= PNG_16_TO_8;
       
   191 }
       
   192 #endif
       
   193 
       
   194 #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
       
   195 void PNGAPI
       
   196 png_set_strip_alpha(png_structp png_ptr)
       
   197 {
       
   198    png_debug(1, "in png_set_strip_alpha");
       
   199 
       
   200    if (png_ptr == NULL)
       
   201       return;
       
   202 
       
   203    png_ptr->transformations |= PNG_STRIP_ALPHA;
       
   204 }
       
   205 #endif
       
   206 
       
   207 #if defined(PNG_READ_ALPHA_MODE_SUPPORTED) || defined(PNG_READ_GAMMA_SUPPORTED)
       
   208 static png_fixed_point
       
   209 translate_gamma_flags(png_structp png_ptr, png_fixed_point output_gamma,
       
   210    int is_screen)
       
   211 {
       
   212    /* Check for flag values.  The main reason for having the old Mac value as a
       
   213     * flag is that it is pretty near impossible to work out what the correct
       
   214     * value is from Apple documentation - a working Mac system is needed to
       
   215     * discover the value!
       
   216     */
       
   217    if (output_gamma == PNG_DEFAULT_sRGB ||
       
   218       output_gamma == PNG_FP_1 / PNG_DEFAULT_sRGB)
       
   219    {
       
   220       /* If there is no sRGB support this just sets the gamma to the standard
       
   221        * sRGB value.  (This is a side effect of using this function!)
       
   222        */
       
   223 #     ifdef PNG_READ_sRGB_SUPPORTED
       
   224          png_ptr->flags |= PNG_FLAG_ASSUME_sRGB;
       
   225 #     endif
       
   226       if (is_screen)
       
   227          output_gamma = PNG_GAMMA_sRGB;
       
   228       else
       
   229          output_gamma = PNG_GAMMA_sRGB_INVERSE;
       
   230    }
       
   231 
       
   232    else if (output_gamma == PNG_GAMMA_MAC_18 ||
       
   233       output_gamma == PNG_FP_1 / PNG_GAMMA_MAC_18)
       
   234    {
       
   235       if (is_screen)
       
   236          output_gamma = PNG_GAMMA_MAC_OLD;
       
   237       else
       
   238          output_gamma = PNG_GAMMA_MAC_INVERSE;
       
   239    }
       
   240 
       
   241    return output_gamma;
       
   242 }
       
   243 
       
   244 #  ifdef PNG_FLOATING_POINT_SUPPORTED
       
   245 static png_fixed_point
       
   246 convert_gamma_value(png_structp png_ptr, double output_gamma)
       
   247 {
       
   248    /* The following silently ignores cases where fixed point (times 100,000)
       
   249     * gamma values are passed to the floating point API.  This is safe and it
       
   250     * means the fixed point constants work just fine with the floating point
       
   251     * API.  The alternative would just lead to undetected errors and spurious
       
   252     * bug reports.  Negative values fail inside the _fixed API unless they
       
   253     * correspond to the flag values.
       
   254     */
       
   255    if (output_gamma > 0 && output_gamma < 128)
       
   256       output_gamma *= PNG_FP_1;
       
   257 
       
   258    /* This preserves -1 and -2 exactly: */
       
   259    output_gamma = floor(output_gamma + .5);
       
   260 
       
   261    if (output_gamma > PNG_FP_MAX || output_gamma < PNG_FP_MIN)
       
   262       png_fixed_error(png_ptr, "gamma value");
       
   263 
       
   264    return (png_fixed_point)output_gamma;
       
   265 }
       
   266 #  endif
       
   267 #endif /* READ_ALPHA_MODE || READ_GAMMA */
       
   268 
       
   269 #ifdef PNG_READ_ALPHA_MODE_SUPPORTED
       
   270 void PNGFAPI
       
   271 png_set_alpha_mode_fixed(png_structp png_ptr, int mode,
       
   272    png_fixed_point output_gamma)
       
   273 {
       
   274    int compose = 0;
       
   275    png_fixed_point file_gamma;
       
   276 
       
   277    png_debug(1, "in png_set_alpha_mode");
       
   278 
       
   279    if (png_ptr == NULL)
       
   280       return;
       
   281 
       
   282    output_gamma = translate_gamma_flags(png_ptr, output_gamma, 1/*screen*/);
       
   283 
       
   284    /* Validate the value to ensure it is in a reasonable range. The value
       
   285     * is expected to be 1 or greater, but this range test allows for some
       
   286     * viewing correction values.  The intent is to weed out users of this API
       
   287     * who use the inverse of the gamma value accidentally!  Since some of these
       
   288     * values are reasonable this may have to be changed.
       
   289     */
       
   290    if (output_gamma < 70000 || output_gamma > 300000)
       
   291       png_error(png_ptr, "output gamma out of expected range");
       
   292 
       
   293    /* The default file gamma is the inverse of the output gamma; the output
       
   294     * gamma may be changed below so get the file value first:
       
   295     */
       
   296    file_gamma = png_reciprocal(output_gamma);
       
   297 
       
   298    /* There are really 8 possibilities here, composed of any combination
       
   299     * of:
       
   300     *
       
   301     *    premultiply the color channels
       
   302     *    do not encode non-opaque pixels
       
   303     *    encode the alpha as well as the color channels
       
   304     *
       
   305     * The differences disappear if the input/output ('screen') gamma is 1.0,
       
   306     * because then the encoding is a no-op and there is only the choice of
       
   307     * premultiplying the color channels or not.
       
   308     *
       
   309     * png_set_alpha_mode and png_set_background interact because both use
       
   310     * png_compose to do the work.  Calling both is only useful when
       
   311     * png_set_alpha_mode is used to set the default mode - PNG_ALPHA_PNG - along
       
   312     * with a default gamma value.  Otherwise PNG_COMPOSE must not be set.
       
   313     */
       
   314    switch (mode)
       
   315    {
       
   316       case PNG_ALPHA_PNG:        /* default: png standard */
       
   317          /* No compose, but it may be set by png_set_background! */
       
   318          png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
       
   319          png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
       
   320          break;
       
   321 
       
   322       case PNG_ALPHA_ASSOCIATED: /* color channels premultiplied */
       
   323          compose = 1;
       
   324          png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
       
   325          png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
       
   326          /* The output is linear: */
       
   327          output_gamma = PNG_FP_1;
       
   328          break;
       
   329 
       
   330       case PNG_ALPHA_OPTIMIZED:  /* associated, non-opaque pixels linear */
       
   331          compose = 1;
       
   332          png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
       
   333          png_ptr->flags |= PNG_FLAG_OPTIMIZE_ALPHA;
       
   334          /* output_gamma records the encoding of opaque pixels! */
       
   335          break;
       
   336 
       
   337       case PNG_ALPHA_BROKEN:     /* associated, non-linear, alpha encoded */
       
   338          compose = 1;
       
   339          png_ptr->transformations |= PNG_ENCODE_ALPHA;
       
   340          png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
       
   341          break;
       
   342 
       
   343       default:
       
   344          png_error(png_ptr, "invalid alpha mode");
       
   345    }
       
   346 
       
   347    /* Only set the default gamma if the file gamma has not been set (this has
       
   348     * the side effect that the gamma in a second call to png_set_alpha_mode will
       
   349     * be ignored.)
       
   350     */
       
   351    if (png_ptr->gamma == 0)
       
   352       png_ptr->gamma = file_gamma;
       
   353 
       
   354    /* But always set the output gamma: */
       
   355    png_ptr->screen_gamma = output_gamma;
       
   356 
       
   357    /* Finally, if pre-multiplying, set the background fields to achieve the
       
   358     * desired result.
       
   359     */
       
   360    if (compose)
       
   361    {
       
   362       /* And obtain alpha pre-multiplication by composing on black: */
       
   363       png_memset(&png_ptr->background, 0, sizeof png_ptr->background);
       
   364       png_ptr->background_gamma = png_ptr->gamma; /* just in case */
       
   365       png_ptr->background_gamma_type = PNG_BACKGROUND_GAMMA_FILE;
       
   366       png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND;
       
   367 
       
   368       if (png_ptr->transformations & PNG_COMPOSE)
       
   369          png_error(png_ptr,
       
   370             "conflicting calls to set alpha mode and background");
       
   371 
       
   372       png_ptr->transformations |= PNG_COMPOSE;
       
   373    }
       
   374 
       
   375    /* New API, make sure apps call the correct initializers: */
       
   376    png_ptr->flags |= PNG_FLAG_DETECT_UNINITIALIZED;
       
   377 }
       
   378 
       
   379 #  ifdef PNG_FLOATING_POINT_SUPPORTED
       
   380 void PNGAPI
       
   381 png_set_alpha_mode(png_structp png_ptr, int mode, double output_gamma)
       
   382 {
       
   383    png_set_alpha_mode_fixed(png_ptr, mode, convert_gamma_value(png_ptr,
       
   384       output_gamma));
       
   385 }
       
   386 #  endif
       
   387 #endif
       
   388 
       
   389 #ifdef PNG_READ_QUANTIZE_SUPPORTED
       
   390 /* Dither file to 8-bit.  Supply a palette, the current number
       
   391  * of elements in the palette, the maximum number of elements
       
   392  * allowed, and a histogram if possible.  If the current number
       
   393  * of colors is greater then the maximum number, the palette will be
       
   394  * modified to fit in the maximum number.  "full_quantize" indicates
       
   395  * whether we need a quantizing cube set up for RGB images, or if we
       
   396  * simply are reducing the number of colors in a paletted image.
       
   397  */
       
   398 
       
   399 typedef struct png_dsort_struct
       
   400 {
       
   401    struct png_dsort_struct FAR * next;
       
   402    png_byte left;
       
   403    png_byte right;
       
   404 } png_dsort;
       
   405 typedef png_dsort FAR *       png_dsortp;
       
   406 typedef png_dsort FAR * FAR * png_dsortpp;
       
   407 
       
   408 void PNGAPI
       
   409 png_set_quantize(png_structp png_ptr, png_colorp palette,
       
   410     int num_palette, int maximum_colors, png_const_uint_16p histogram,
       
   411     int full_quantize)
       
   412 {
       
   413    png_debug(1, "in png_set_quantize");
       
   414 
       
   415    if (png_ptr == NULL)
       
   416       return;
       
   417 
       
   418    png_ptr->transformations |= PNG_QUANTIZE;
       
   419 
       
   420    if (!full_quantize)
       
   421    {
       
   422       int i;
       
   423 
       
   424       png_ptr->quantize_index = (png_bytep)png_malloc(png_ptr,
       
   425           (png_uint_32)(num_palette * png_sizeof(png_byte)));
       
   426       for (i = 0; i < num_palette; i++)
       
   427          png_ptr->quantize_index[i] = (png_byte)i;
       
   428    }
       
   429 
       
   430    if (num_palette > maximum_colors)
       
   431    {
       
   432       if (histogram != NULL)
       
   433       {
       
   434          /* This is easy enough, just throw out the least used colors.
       
   435           * Perhaps not the best solution, but good enough.
       
   436           */
       
   437 
       
   438          int i;
       
   439 
       
   440          /* Initialize an array to sort colors */
       
   441          png_ptr->quantize_sort = (png_bytep)png_malloc(png_ptr,
       
   442              (png_uint_32)(num_palette * png_sizeof(png_byte)));
       
   443 
       
   444          /* Initialize the quantize_sort array */
       
   445          for (i = 0; i < num_palette; i++)
       
   446             png_ptr->quantize_sort[i] = (png_byte)i;
       
   447 
       
   448          /* Find the least used palette entries by starting a
       
   449           * bubble sort, and running it until we have sorted
       
   450           * out enough colors.  Note that we don't care about
       
   451           * sorting all the colors, just finding which are
       
   452           * least used.
       
   453           */
       
   454 
       
   455          for (i = num_palette - 1; i >= maximum_colors; i--)
       
   456          {
       
   457             int done; /* To stop early if the list is pre-sorted */
       
   458             int j;
       
   459 
       
   460             done = 1;
       
   461             for (j = 0; j < i; j++)
       
   462             {
       
   463                if (histogram[png_ptr->quantize_sort[j]]
       
   464                    < histogram[png_ptr->quantize_sort[j + 1]])
       
   465                {
       
   466                   png_byte t;
       
   467 
       
   468                   t = png_ptr->quantize_sort[j];
       
   469                   png_ptr->quantize_sort[j] = png_ptr->quantize_sort[j + 1];
       
   470                   png_ptr->quantize_sort[j + 1] = t;
       
   471                   done = 0;
       
   472                }
       
   473             }
       
   474 
       
   475             if (done)
       
   476                break;
       
   477          }
       
   478 
       
   479          /* Swap the palette around, and set up a table, if necessary */
       
   480          if (full_quantize)
       
   481          {
       
   482             int j = num_palette;
       
   483 
       
   484             /* Put all the useful colors within the max, but don't
       
   485              * move the others.
       
   486              */
       
   487             for (i = 0; i < maximum_colors; i++)
       
   488             {
       
   489                if ((int)png_ptr->quantize_sort[i] >= maximum_colors)
       
   490                {
       
   491                   do
       
   492                      j--;
       
   493                   while ((int)png_ptr->quantize_sort[j] >= maximum_colors);
       
   494 
       
   495                   palette[i] = palette[j];
       
   496                }
       
   497             }
       
   498          }
       
   499          else
       
   500          {
       
   501             int j = num_palette;
       
   502 
       
   503             /* Move all the used colors inside the max limit, and
       
   504              * develop a translation table.
       
   505              */
       
   506             for (i = 0; i < maximum_colors; i++)
       
   507             {
       
   508                /* Only move the colors we need to */
       
   509                if ((int)png_ptr->quantize_sort[i] >= maximum_colors)
       
   510                {
       
   511                   png_color tmp_color;
       
   512 
       
   513                   do
       
   514                      j--;
       
   515                   while ((int)png_ptr->quantize_sort[j] >= maximum_colors);
       
   516 
       
   517                   tmp_color = palette[j];
       
   518                   palette[j] = palette[i];
       
   519                   palette[i] = tmp_color;
       
   520                   /* Indicate where the color went */
       
   521                   png_ptr->quantize_index[j] = (png_byte)i;
       
   522                   png_ptr->quantize_index[i] = (png_byte)j;
       
   523                }
       
   524             }
       
   525 
       
   526             /* Find closest color for those colors we are not using */
       
   527             for (i = 0; i < num_palette; i++)
       
   528             {
       
   529                if ((int)png_ptr->quantize_index[i] >= maximum_colors)
       
   530                {
       
   531                   int min_d, k, min_k, d_index;
       
   532 
       
   533                   /* Find the closest color to one we threw out */
       
   534                   d_index = png_ptr->quantize_index[i];
       
   535                   min_d = PNG_COLOR_DIST(palette[d_index], palette[0]);
       
   536                   for (k = 1, min_k = 0; k < maximum_colors; k++)
       
   537                   {
       
   538                      int d;
       
   539 
       
   540                      d = PNG_COLOR_DIST(palette[d_index], palette[k]);
       
   541 
       
   542                      if (d < min_d)
       
   543                      {
       
   544                         min_d = d;
       
   545                         min_k = k;
       
   546                      }
       
   547                   }
       
   548                   /* Point to closest color */
       
   549                   png_ptr->quantize_index[i] = (png_byte)min_k;
       
   550                }
       
   551             }
       
   552          }
       
   553          png_free(png_ptr, png_ptr->quantize_sort);
       
   554          png_ptr->quantize_sort = NULL;
       
   555       }
       
   556       else
       
   557       {
       
   558          /* This is much harder to do simply (and quickly).  Perhaps
       
   559           * we need to go through a median cut routine, but those
       
   560           * don't always behave themselves with only a few colors
       
   561           * as input.  So we will just find the closest two colors,
       
   562           * and throw out one of them (chosen somewhat randomly).
       
   563           * [We don't understand this at all, so if someone wants to
       
   564           *  work on improving it, be our guest - AED, GRP]
       
   565           */
       
   566          int i;
       
   567          int max_d;
       
   568          int num_new_palette;
       
   569          png_dsortp t;
       
   570          png_dsortpp hash;
       
   571 
       
   572          t = NULL;
       
   573 
       
   574          /* Initialize palette index arrays */
       
   575          png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr,
       
   576              (png_uint_32)(num_palette * png_sizeof(png_byte)));
       
   577          png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr,
       
   578              (png_uint_32)(num_palette * png_sizeof(png_byte)));
       
   579 
       
   580          /* Initialize the sort array */
       
   581          for (i = 0; i < num_palette; i++)
       
   582          {
       
   583             png_ptr->index_to_palette[i] = (png_byte)i;
       
   584             png_ptr->palette_to_index[i] = (png_byte)i;
       
   585          }
       
   586 
       
   587          hash = (png_dsortpp)png_calloc(png_ptr, (png_uint_32)(769 *
       
   588              png_sizeof(png_dsortp)));
       
   589 
       
   590          num_new_palette = num_palette;
       
   591 
       
   592          /* Initial wild guess at how far apart the farthest pixel
       
   593           * pair we will be eliminating will be.  Larger
       
   594           * numbers mean more areas will be allocated, Smaller
       
   595           * numbers run the risk of not saving enough data, and
       
   596           * having to do this all over again.
       
   597           *
       
   598           * I have not done extensive checking on this number.
       
   599           */
       
   600          max_d = 96;
       
   601 
       
   602          while (num_new_palette > maximum_colors)
       
   603          {
       
   604             for (i = 0; i < num_new_palette - 1; i++)
       
   605             {
       
   606                int j;
       
   607 
       
   608                for (j = i + 1; j < num_new_palette; j++)
       
   609                {
       
   610                   int d;
       
   611 
       
   612                   d = PNG_COLOR_DIST(palette[i], palette[j]);
       
   613 
       
   614                   if (d <= max_d)
       
   615                   {
       
   616 
       
   617                      t = (png_dsortp)png_malloc_warn(png_ptr,
       
   618                          (png_uint_32)(png_sizeof(png_dsort)));
       
   619 
       
   620                      if (t == NULL)
       
   621                          break;
       
   622 
       
   623                      t->next = hash[d];
       
   624                      t->left = (png_byte)i;
       
   625                      t->right = (png_byte)j;
       
   626                      hash[d] = t;
       
   627                   }
       
   628                }
       
   629                if (t == NULL)
       
   630                   break;
       
   631             }
       
   632 
       
   633             if (t != NULL)
       
   634             for (i = 0; i <= max_d; i++)
       
   635             {
       
   636                if (hash[i] != NULL)
       
   637                {
       
   638                   png_dsortp p;
       
   639 
       
   640                   for (p = hash[i]; p; p = p->next)
       
   641                   {
       
   642                      if ((int)png_ptr->index_to_palette[p->left]
       
   643                          < num_new_palette &&
       
   644                          (int)png_ptr->index_to_palette[p->right]
       
   645                          < num_new_palette)
       
   646                      {
       
   647                         int j, next_j;
       
   648 
       
   649                         if (num_new_palette & 0x01)
       
   650                         {
       
   651                            j = p->left;
       
   652                            next_j = p->right;
       
   653                         }
       
   654                         else
       
   655                         {
       
   656                            j = p->right;
       
   657                            next_j = p->left;
       
   658                         }
       
   659 
       
   660                         num_new_palette--;
       
   661                         palette[png_ptr->index_to_palette[j]]
       
   662                             = palette[num_new_palette];
       
   663                         if (!full_quantize)
       
   664                         {
       
   665                            int k;
       
   666 
       
   667                            for (k = 0; k < num_palette; k++)
       
   668                            {
       
   669                               if (png_ptr->quantize_index[k] ==
       
   670                                   png_ptr->index_to_palette[j])
       
   671                                  png_ptr->quantize_index[k] =
       
   672                                      png_ptr->index_to_palette[next_j];
       
   673 
       
   674                               if ((int)png_ptr->quantize_index[k] ==
       
   675                                   num_new_palette)
       
   676                                  png_ptr->quantize_index[k] =
       
   677                                      png_ptr->index_to_palette[j];
       
   678                            }
       
   679                         }
       
   680 
       
   681                         png_ptr->index_to_palette[png_ptr->palette_to_index
       
   682                             [num_new_palette]] = png_ptr->index_to_palette[j];
       
   683 
       
   684                         png_ptr->palette_to_index[png_ptr->index_to_palette[j]]
       
   685                             = png_ptr->palette_to_index[num_new_palette];
       
   686 
       
   687                         png_ptr->index_to_palette[j] =
       
   688                             (png_byte)num_new_palette;
       
   689 
       
   690                         png_ptr->palette_to_index[num_new_palette] =
       
   691                             (png_byte)j;
       
   692                      }
       
   693                      if (num_new_palette <= maximum_colors)
       
   694                         break;
       
   695                   }
       
   696                   if (num_new_palette <= maximum_colors)
       
   697                      break;
       
   698                }
       
   699             }
       
   700 
       
   701             for (i = 0; i < 769; i++)
       
   702             {
       
   703                if (hash[i] != NULL)
       
   704                {
       
   705                   png_dsortp p = hash[i];
       
   706                   while (p)
       
   707                   {
       
   708                      t = p->next;
       
   709                      png_free(png_ptr, p);
       
   710                      p = t;
       
   711                   }
       
   712                }
       
   713                hash[i] = 0;
       
   714             }
       
   715             max_d += 96;
       
   716          }
       
   717          png_free(png_ptr, hash);
       
   718          png_free(png_ptr, png_ptr->palette_to_index);
       
   719          png_free(png_ptr, png_ptr->index_to_palette);
       
   720          png_ptr->palette_to_index = NULL;
       
   721          png_ptr->index_to_palette = NULL;
       
   722       }
       
   723       num_palette = maximum_colors;
       
   724    }
       
   725    if (png_ptr->palette == NULL)
       
   726    {
       
   727       png_ptr->palette = palette;
       
   728    }
       
   729    png_ptr->num_palette = (png_uint_16)num_palette;
       
   730 
       
   731    if (full_quantize)
       
   732    {
       
   733       int i;
       
   734       png_bytep distance;
       
   735       int total_bits = PNG_QUANTIZE_RED_BITS + PNG_QUANTIZE_GREEN_BITS +
       
   736           PNG_QUANTIZE_BLUE_BITS;
       
   737       int num_red = (1 << PNG_QUANTIZE_RED_BITS);
       
   738       int num_green = (1 << PNG_QUANTIZE_GREEN_BITS);
       
   739       int num_blue = (1 << PNG_QUANTIZE_BLUE_BITS);
       
   740       png_size_t num_entries = ((png_size_t)1 << total_bits);
       
   741 
       
   742       png_ptr->palette_lookup = (png_bytep)png_calloc(png_ptr,
       
   743           (png_uint_32)(num_entries * png_sizeof(png_byte)));
       
   744 
       
   745       distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries *
       
   746           png_sizeof(png_byte)));
       
   747 
       
   748       png_memset(distance, 0xff, num_entries * png_sizeof(png_byte));
       
   749 
       
   750       for (i = 0; i < num_palette; i++)
       
   751       {
       
   752          int ir, ig, ib;
       
   753          int r = (palette[i].red >> (8 - PNG_QUANTIZE_RED_BITS));
       
   754          int g = (palette[i].green >> (8 - PNG_QUANTIZE_GREEN_BITS));
       
   755          int b = (palette[i].blue >> (8 - PNG_QUANTIZE_BLUE_BITS));
       
   756 
       
   757          for (ir = 0; ir < num_red; ir++)
       
   758          {
       
   759             /* int dr = abs(ir - r); */
       
   760             int dr = ((ir > r) ? ir - r : r - ir);
       
   761             int index_r = (ir << (PNG_QUANTIZE_BLUE_BITS +
       
   762                 PNG_QUANTIZE_GREEN_BITS));
       
   763 
       
   764             for (ig = 0; ig < num_green; ig++)
       
   765             {
       
   766                /* int dg = abs(ig - g); */
       
   767                int dg = ((ig > g) ? ig - g : g - ig);
       
   768                int dt = dr + dg;
       
   769                int dm = ((dr > dg) ? dr : dg);
       
   770                int index_g = index_r | (ig << PNG_QUANTIZE_BLUE_BITS);
       
   771 
       
   772                for (ib = 0; ib < num_blue; ib++)
       
   773                {
       
   774                   int d_index = index_g | ib;
       
   775                   /* int db = abs(ib - b); */
       
   776                   int db = ((ib > b) ? ib - b : b - ib);
       
   777                   int dmax = ((dm > db) ? dm : db);
       
   778                   int d = dmax + dt + db;
       
   779 
       
   780                   if (d < (int)distance[d_index])
       
   781                   {
       
   782                      distance[d_index] = (png_byte)d;
       
   783                      png_ptr->palette_lookup[d_index] = (png_byte)i;
       
   784                   }
       
   785                }
       
   786             }
       
   787          }
       
   788       }
       
   789 
       
   790       png_free(png_ptr, distance);
       
   791    }
       
   792 }
       
   793 #endif /* PNG_READ_QUANTIZE_SUPPORTED */
       
   794 
       
   795 #ifdef PNG_READ_GAMMA_SUPPORTED
       
   796 void PNGFAPI
       
   797 png_set_gamma_fixed(png_structp png_ptr, png_fixed_point scrn_gamma,
       
   798    png_fixed_point file_gamma)
       
   799 {
       
   800    png_debug(1, "in png_set_gamma_fixed");
       
   801 
       
   802    if (png_ptr == NULL)
       
   803       return;
       
   804 
       
   805    /* New in libpng-1.5.4 - reserve particular negative values as flags. */
       
   806    scrn_gamma = translate_gamma_flags(png_ptr, scrn_gamma, 1/*screen*/);
       
   807    file_gamma = translate_gamma_flags(png_ptr, file_gamma, 0/*file*/);
       
   808 
       
   809 #if PNG_LIBPNG_VER >= 10600
       
   810    /* Checking the gamma values for being >0 was added in 1.5.4 along with the
       
   811     * premultiplied alpha support; this actually hides an undocumented feature
       
   812     * of the previous implementation which allowed gamma processing to be
       
   813     * disabled in background handling.  There is no evidence (so far) that this
       
   814     * was being used; however, png_set_background itself accepted and must still
       
   815     * accept '0' for the gamma value it takes, because it isn't always used.
       
   816     *
       
   817     * Since this is an API change (albeit a very minor one that removes an
       
   818     * undocumented API feature) it will not be made until libpng-1.6.0.
       
   819     */
       
   820    if (file_gamma <= 0)
       
   821       png_error(png_ptr, "invalid file gamma in png_set_gamma");
       
   822 
       
   823    if (scrn_gamma <= 0)
       
   824       png_error(png_ptr, "invalid screen gamma in png_set_gamma");
       
   825 #endif
       
   826 
       
   827    /* Set the gamma values unconditionally - this overrides the value in the PNG
       
   828     * file if a gAMA chunk was present.  png_set_alpha_mode provides a
       
   829     * different, easier, way to default the file gamma.
       
   830     */
       
   831    png_ptr->gamma = file_gamma;
       
   832    png_ptr->screen_gamma = scrn_gamma;
       
   833 }
       
   834 
       
   835 #  ifdef PNG_FLOATING_POINT_SUPPORTED
       
   836 void PNGAPI
       
   837 png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma)
       
   838 {
       
   839    png_set_gamma_fixed(png_ptr, convert_gamma_value(png_ptr, scrn_gamma),
       
   840       convert_gamma_value(png_ptr, file_gamma));
       
   841 }
       
   842 #  endif /* FLOATING_POINT_SUPPORTED */
       
   843 #endif /* READ_GAMMA */
       
   844 
       
   845 #ifdef PNG_READ_EXPAND_SUPPORTED
       
   846 /* Expand paletted images to RGB, expand grayscale images of
       
   847  * less than 8-bit depth to 8-bit depth, and expand tRNS chunks
       
   848  * to alpha channels.
       
   849  */
       
   850 void PNGAPI
       
   851 png_set_expand(png_structp png_ptr)
       
   852 {
       
   853    png_debug(1, "in png_set_expand");
       
   854 
       
   855    if (png_ptr == NULL)
       
   856       return;
       
   857 
       
   858    png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
       
   859    png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
       
   860 }
       
   861 
       
   862 /* GRR 19990627:  the following three functions currently are identical
       
   863  *  to png_set_expand().  However, it is entirely reasonable that someone
       
   864  *  might wish to expand an indexed image to RGB but *not* expand a single,
       
   865  *  fully transparent palette entry to a full alpha channel--perhaps instead
       
   866  *  convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace
       
   867  *  the transparent color with a particular RGB value, or drop tRNS entirely.
       
   868  *  IOW, a future version of the library may make the transformations flag
       
   869  *  a bit more fine-grained, with separate bits for each of these three
       
   870  *  functions.
       
   871  *
       
   872  *  More to the point, these functions make it obvious what libpng will be
       
   873  *  doing, whereas "expand" can (and does) mean any number of things.
       
   874  *
       
   875  *  GRP 20060307: In libpng-1.2.9, png_set_gray_1_2_4_to_8() was modified
       
   876  *  to expand only the sample depth but not to expand the tRNS to alpha
       
   877  *  and its name was changed to png_set_expand_gray_1_2_4_to_8().
       
   878  */
       
   879 
       
   880 /* Expand paletted images to RGB. */
       
   881 void PNGAPI
       
   882 png_set_palette_to_rgb(png_structp png_ptr)
       
   883 {
       
   884    png_debug(1, "in png_set_palette_to_rgb");
       
   885 
       
   886    if (png_ptr == NULL)
       
   887       return;
       
   888 
       
   889    png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
       
   890    png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
       
   891 }
       
   892 
       
   893 /* Expand grayscale images of less than 8-bit depth to 8 bits. */
       
   894 void PNGAPI
       
   895 png_set_expand_gray_1_2_4_to_8(png_structp png_ptr)
       
   896 {
       
   897    png_debug(1, "in png_set_expand_gray_1_2_4_to_8");
       
   898 
       
   899    if (png_ptr == NULL)
       
   900       return;
       
   901 
       
   902    png_ptr->transformations |= PNG_EXPAND;
       
   903    png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
       
   904 }
       
   905 
       
   906 
       
   907 
       
   908 /* Expand tRNS chunks to alpha channels. */
       
   909 void PNGAPI
       
   910 png_set_tRNS_to_alpha(png_structp png_ptr)
       
   911 {
       
   912    png_debug(1, "in png_set_tRNS_to_alpha");
       
   913 
       
   914    png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
       
   915    png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
       
   916 }
       
   917 #endif /* defined(PNG_READ_EXPAND_SUPPORTED) */
       
   918 
       
   919 #ifdef PNG_READ_EXPAND_16_SUPPORTED
       
   920 /* Expand to 16-bit channels, expand the tRNS chunk too (because otherwise
       
   921  * it may not work correctly.)
       
   922  */
       
   923 void PNGAPI
       
   924 png_set_expand_16(png_structp png_ptr)
       
   925 {
       
   926    png_debug(1, "in png_set_expand_16");
       
   927 
       
   928    if (png_ptr == NULL)
       
   929       return;
       
   930 
       
   931    png_ptr->transformations |= (PNG_EXPAND_16 | PNG_EXPAND | PNG_EXPAND_tRNS);
       
   932    png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
       
   933 
       
   934    /* New API, make sure apps call the correct initializers: */
       
   935    png_ptr->flags |= PNG_FLAG_DETECT_UNINITIALIZED;
       
   936 }
       
   937 #endif
       
   938 
       
   939 #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
       
   940 void PNGAPI
       
   941 png_set_gray_to_rgb(png_structp png_ptr)
       
   942 {
       
   943    png_debug(1, "in png_set_gray_to_rgb");
       
   944 
       
   945    if (png_ptr != NULL)
       
   946    {
       
   947       /* Because rgb must be 8 bits or more: */
       
   948       png_set_expand_gray_1_2_4_to_8(png_ptr);
       
   949       png_ptr->transformations |= PNG_GRAY_TO_RGB;
       
   950       png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
       
   951    }
       
   952 }
       
   953 #endif
       
   954 
       
   955 #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
       
   956 void PNGFAPI
       
   957 png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action,
       
   958     png_fixed_point red, png_fixed_point green)
       
   959 {
       
   960    png_debug(1, "in png_set_rgb_to_gray");
       
   961 
       
   962    if (png_ptr == NULL)
       
   963       return;
       
   964 
       
   965    switch(error_action)
       
   966    {
       
   967       case 1:
       
   968          png_ptr->transformations |= PNG_RGB_TO_GRAY;
       
   969          break;
       
   970 
       
   971       case 2:
       
   972          png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN;
       
   973          break;
       
   974 
       
   975       case 3:
       
   976          png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR;
       
   977          break;
       
   978 
       
   979       default:
       
   980          png_error(png_ptr, "invalid error action to rgb_to_gray");
       
   981          break;
       
   982    }
       
   983    if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
       
   984 #ifdef PNG_READ_EXPAND_SUPPORTED
       
   985       png_ptr->transformations |= PNG_EXPAND;
       
   986 #else
       
   987    {
       
   988       png_warning(png_ptr,
       
   989         "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED");
       
   990 
       
   991       png_ptr->transformations &= ~PNG_RGB_TO_GRAY;
       
   992    }
       
   993 #endif
       
   994    {
       
   995       if (red >= 0 && green >= 0 && red + green <= PNG_FP_1)
       
   996       {
       
   997          png_uint_16 red_int, green_int;
       
   998 
       
   999          red_int = (png_uint_16)(((png_uint_32)red*32768L)/100000L);
       
  1000          green_int = (png_uint_16)(((png_uint_32)green*32768L)/100000L);
       
  1001 
       
  1002          png_ptr->rgb_to_gray_red_coeff   = red_int;
       
  1003          png_ptr->rgb_to_gray_green_coeff = green_int;
       
  1004          png_ptr->rgb_to_gray_blue_coeff  =
       
  1005           (png_uint_16)(32768 - red_int - green_int);
       
  1006       }
       
  1007 
       
  1008       else
       
  1009       {
       
  1010          if (red >= 0 && green >= 0)
       
  1011             png_warning(png_ptr,
       
  1012                "ignoring out of range rgb_to_gray coefficients");
       
  1013 
       
  1014          /* Use the defaults, from the cHRM chunk if set, else the built in Rec
       
  1015           * 709 values (which correspond to sRGB, so we don't have to worry
       
  1016           * about the sRGB chunk!)
       
  1017           */
       
  1018          if (png_ptr->rgb_to_gray_red_coeff == 0 &&
       
  1019             png_ptr->rgb_to_gray_green_coeff == 0 &&
       
  1020             png_ptr->rgb_to_gray_blue_coeff == 0)
       
  1021          {
       
  1022             png_ptr->rgb_to_gray_red_coeff   = 6968;  /* .212671 * 32768 + .5 */
       
  1023             png_ptr->rgb_to_gray_green_coeff = 23434; /* .715160 * 32768 + .5 */
       
  1024             png_ptr->rgb_to_gray_blue_coeff  = 2366;
       
  1025          }
       
  1026       }
       
  1027    }
       
  1028 }
       
  1029 
       
  1030 #ifdef PNG_FLOATING_POINT_SUPPORTED
       
  1031 /* Convert a RGB image to a grayscale of the same width.  This allows us,
       
  1032  * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image.
       
  1033  */
       
  1034 
       
  1035 void PNGAPI
       
  1036 png_set_rgb_to_gray(png_structp png_ptr, int error_action, double red,
       
  1037    double green)
       
  1038 {
       
  1039    if (png_ptr == NULL)
       
  1040       return;
       
  1041 
       
  1042    png_set_rgb_to_gray_fixed(png_ptr, error_action,
       
  1043       png_fixed(png_ptr, red, "rgb to gray red coefficient"),
       
  1044       png_fixed(png_ptr, green, "rgb to gray green coefficient"));
       
  1045 }
       
  1046 #endif /* FLOATING POINT */
       
  1047 
       
  1048 #endif
       
  1049 
       
  1050 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
       
  1051     defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
       
  1052 void PNGAPI
       
  1053 png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr
       
  1054     read_user_transform_fn)
       
  1055 {
       
  1056    png_debug(1, "in png_set_read_user_transform_fn");
       
  1057 
       
  1058    if (png_ptr == NULL)
       
  1059       return;
       
  1060 
       
  1061 #ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
       
  1062    png_ptr->transformations |= PNG_USER_TRANSFORM;
       
  1063    png_ptr->read_user_transform_fn = read_user_transform_fn;
       
  1064 #endif
       
  1065 }
       
  1066 #endif
       
  1067 
       
  1068 #ifdef PNG_READ_TRANSFORMS_SUPPORTED
       
  1069 #ifdef PNG_READ_GAMMA_SUPPORTED
       
  1070 /* In the case of gamma transformations only do transformations on images where
       
  1071  * the [file] gamma and screen_gamma are not close reciprocals, otherwise it
       
  1072  * slows things down slightly, and also needlessly introduces small errors.
       
  1073  */
       
  1074 static int /* PRIVATE */
       
  1075 png_gamma_threshold(png_fixed_point screen_gamma, png_fixed_point file_gamma)
       
  1076 {
       
  1077    /* PNG_GAMMA_THRESHOLD is the threshold for performing gamma
       
  1078     * correction as a difference of the overall transform from 1.0
       
  1079     *
       
  1080     * We want to compare the threshold with s*f - 1, if we get
       
  1081     * overflow here it is because of wacky gamma values so we
       
  1082     * turn on processing anyway.
       
  1083     */
       
  1084    png_fixed_point gtest;
       
  1085    return !png_muldiv(&gtest, screen_gamma, file_gamma, PNG_FP_1) ||
       
  1086        png_gamma_significant(gtest);
       
  1087 }
       
  1088 #endif
       
  1089 
       
  1090 /* Initialize everything needed for the read.  This includes modifying
       
  1091  * the palette.
       
  1092  */
       
  1093 
       
  1094 /*For the moment 'png_init_palette_transformations' and
       
  1095  * 'png_init_rgb_transformations' only do some flag canceling optimizations.
       
  1096  * The intent is that these two routines should have palette or rgb operations
       
  1097  * extracted from 'png_init_read_transformations'.
       
  1098  */
       
  1099 static void /* PRIVATE */
       
  1100 png_init_palette_transformations(png_structp png_ptr)
       
  1101 {
       
  1102    /* Called to handle the (input) palette case.  In png_do_read_transformations
       
  1103     * the first step is to expand the palette if requested, so this code must
       
  1104     * take care to only make changes that are invariant with respect to the
       
  1105     * palette expansion, or only do them if there is no expansion.
       
  1106     *
       
  1107     * STRIP_ALPHA has already been handled in the caller (by setting num_trans
       
  1108     * to 0.)
       
  1109     */
       
  1110    int input_has_alpha = 0;
       
  1111    int input_has_transparency = 0;
       
  1112 
       
  1113    if (png_ptr->num_trans > 0)
       
  1114    {
       
  1115       int i;
       
  1116 
       
  1117       /* Ignore if all the entries are opaque (unlikely!) */
       
  1118       for (i=0; i<png_ptr->num_trans; ++i)
       
  1119          if (png_ptr->trans_alpha[i] == 255)
       
  1120             continue;
       
  1121          else if (png_ptr->trans_alpha[i] == 0)
       
  1122             input_has_transparency = 1;
       
  1123          else
       
  1124             input_has_alpha = 1;
       
  1125    }
       
  1126 
       
  1127    /* If no alpha we can optimize. */
       
  1128    if (!input_has_alpha)
       
  1129    {
       
  1130       /* Any alpha means background and associative alpha processing is
       
  1131        * required, however if the alpha is 0 or 1 throughout OPTIIMIZE_ALPHA
       
  1132        * and ENCODE_ALPHA are irrelevant.
       
  1133        */
       
  1134       png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
       
  1135       png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
       
  1136 
       
  1137       if (!input_has_transparency)
       
  1138          png_ptr->transformations &= ~(PNG_COMPOSE | PNG_BACKGROUND_EXPAND);
       
  1139    }
       
  1140 
       
  1141 #if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
       
  1142    /* png_set_background handling - deals with the complexity of whether the
       
  1143     * background color is in the file format or the screen format in the case
       
  1144     * where an 'expand' will happen.
       
  1145     */
       
  1146 
       
  1147    /* The following code cannot be entered in the alpha pre-multiplication case
       
  1148     * because PNG_BACKGROUND_EXPAND is cancelled below.
       
  1149     */
       
  1150    if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
       
  1151        (png_ptr->transformations & PNG_EXPAND))
       
  1152    {
       
  1153       {
       
  1154          png_ptr->background.red   =
       
  1155              png_ptr->palette[png_ptr->background.index].red;
       
  1156          png_ptr->background.green =
       
  1157              png_ptr->palette[png_ptr->background.index].green;
       
  1158          png_ptr->background.blue  =
       
  1159              png_ptr->palette[png_ptr->background.index].blue;
       
  1160 
       
  1161 #ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
       
  1162         if (png_ptr->transformations & PNG_INVERT_ALPHA)
       
  1163         {
       
  1164            if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
       
  1165            {
       
  1166               /* Invert the alpha channel (in tRNS) unless the pixels are
       
  1167                * going to be expanded, in which case leave it for later
       
  1168                */
       
  1169               int i, istop = png_ptr->num_trans;
       
  1170 
       
  1171               for (i=0; i<istop; i++)
       
  1172                  png_ptr->trans_alpha[i] = (png_byte)(255 -
       
  1173                     png_ptr->trans_alpha[i]);
       
  1174            }
       
  1175         }
       
  1176 #endif /* PNG_READ_INVERT_ALPHA_SUPPORTED */
       
  1177       }
       
  1178    } /* background expand and (therefore) no alpha association. */
       
  1179 #endif /* PNG_READ_EXPAND_SUPPORTED && PNG_READ_BACKGROUND_SUPPORTED */
       
  1180 }
       
  1181 
       
  1182 static void /* PRIVATE */
       
  1183 png_init_rgb_transformations(png_structp png_ptr)
       
  1184 {
       
  1185    /* Added to libpng-1.5.4: check the color type to determine whether there
       
  1186     * is any alpha or transparency in the image and simply cancel the
       
  1187     * background and alpha mode stuff if there isn't.
       
  1188     */
       
  1189    int input_has_alpha = (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0;
       
  1190    int input_has_transparency = png_ptr->num_trans > 0;
       
  1191 
       
  1192    /* If no alpha we can optimize. */
       
  1193    if (!input_has_alpha)
       
  1194    {
       
  1195       /* Any alpha means background and associative alpha processing is
       
  1196        * required, however if the alpha is 0 or 1 throughout OPTIIMIZE_ALPHA
       
  1197        * and ENCODE_ALPHA are irrelevant.
       
  1198        */
       
  1199 #     ifdef PNG_READ_ALPHA_MODE_SUPPORTED
       
  1200          png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
       
  1201          png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
       
  1202 #     endif
       
  1203 
       
  1204       if (!input_has_transparency)
       
  1205          png_ptr->transformations &= ~(PNG_COMPOSE | PNG_BACKGROUND_EXPAND);
       
  1206    }
       
  1207 
       
  1208 #if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
       
  1209    /* png_set_background handling - deals with the complexity of whether the
       
  1210     * background color is in the file format or the screen format in the case
       
  1211     * where an 'expand' will happen.
       
  1212     */
       
  1213 
       
  1214    /* The following code cannot be entered in the alpha pre-multiplication case
       
  1215     * because PNG_BACKGROUND_EXPAND is cancelled below.
       
  1216     */
       
  1217    if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
       
  1218        (png_ptr->transformations & PNG_EXPAND) &&
       
  1219        !(png_ptr->color_type & PNG_COLOR_MASK_COLOR))
       
  1220        /* i.e., GRAY or GRAY_ALPHA */
       
  1221    {
       
  1222       {
       
  1223          /* Expand background and tRNS chunks */
       
  1224          switch (png_ptr->bit_depth)
       
  1225          {
       
  1226             case 1:
       
  1227                png_ptr->background.gray *= (png_uint_16)0xff;
       
  1228                png_ptr->background.red = png_ptr->background.green
       
  1229                    =  png_ptr->background.blue = png_ptr->background.gray;
       
  1230                if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
       
  1231                {
       
  1232                  png_ptr->trans_color.gray *= (png_uint_16)0xff;
       
  1233                  png_ptr->trans_color.red = png_ptr->trans_color.green
       
  1234                      = png_ptr->trans_color.blue = png_ptr->trans_color.gray;
       
  1235                }
       
  1236                break;
       
  1237 
       
  1238             case 2:
       
  1239                png_ptr->background.gray *= (png_uint_16)0x55;
       
  1240                png_ptr->background.red = png_ptr->background.green
       
  1241                    = png_ptr->background.blue = png_ptr->background.gray;
       
  1242                if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
       
  1243                {
       
  1244                   png_ptr->trans_color.gray *= (png_uint_16)0x55;
       
  1245                   png_ptr->trans_color.red = png_ptr->trans_color.green
       
  1246                       = png_ptr->trans_color.blue = png_ptr->trans_color.gray;
       
  1247                }
       
  1248                break;
       
  1249 
       
  1250             case 4:
       
  1251                png_ptr->background.gray *= (png_uint_16)0x11;
       
  1252                png_ptr->background.red = png_ptr->background.green
       
  1253                    = png_ptr->background.blue = png_ptr->background.gray;
       
  1254                if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
       
  1255                {
       
  1256                   png_ptr->trans_color.gray *= (png_uint_16)0x11;
       
  1257                   png_ptr->trans_color.red = png_ptr->trans_color.green
       
  1258                       = png_ptr->trans_color.blue = png_ptr->trans_color.gray;
       
  1259                }
       
  1260                break;
       
  1261 
       
  1262             default:
       
  1263 
       
  1264             case 8:
       
  1265 
       
  1266             case 16:
       
  1267                png_ptr->background.red = png_ptr->background.green
       
  1268                    = png_ptr->background.blue = png_ptr->background.gray;
       
  1269                break;
       
  1270          }
       
  1271       }
       
  1272    } /* background expand and (therefore) no alpha association. */
       
  1273 #endif /* PNG_READ_EXPAND_SUPPORTED && PNG_READ_BACKGROUND_SUPPORTED */
       
  1274 }
       
  1275 
       
  1276 void /* PRIVATE */
       
  1277 png_init_read_transformations(png_structp png_ptr)
       
  1278 {
       
  1279    png_debug(1, "in png_init_read_transformations");
       
  1280 
       
  1281    /* This internal function is called from png_read_start_row in pngrutil.c
       
  1282     * and it is called before the 'rowbytes' calculation is done, so the code
       
  1283     * in here can change or update the transformations flags.
       
  1284     *
       
  1285     * First do updates that do not depend on the details of the PNG image data
       
  1286     * being processed.
       
  1287     */
       
  1288 
       
  1289 #ifdef PNG_READ_GAMMA_SUPPORTED
       
  1290    /* Prior to 1.5.4 these tests were performed from png_set_gamma, 1.5.4 adds
       
  1291     * png_set_alpha_mode and this is another source for a default file gamma so
       
  1292     * the test needs to be performed later - here.  In addition prior to 1.5.4
       
  1293     * the tests were repeated for the PALETTE color type here - this is no
       
  1294     * longer necessary (and doesn't seem to have been necessary before.)
       
  1295     */
       
  1296    {
       
  1297       /* The following temporary indicates if overall gamma correction is
       
  1298        * required.
       
  1299        */
       
  1300       int gamma_correction = 0;
       
  1301 
       
  1302       if (png_ptr->gamma != 0) /* has been set */
       
  1303       {
       
  1304          if (png_ptr->screen_gamma != 0) /* screen set too */
       
  1305             gamma_correction = png_gamma_threshold(png_ptr->gamma,
       
  1306                png_ptr->screen_gamma);
       
  1307 
       
  1308          else
       
  1309             /* Assume the output matches the input; a long time default behavior
       
  1310              * of libpng, although the standard has nothing to say about this.
       
  1311              */
       
  1312             png_ptr->screen_gamma = png_reciprocal(png_ptr->gamma);
       
  1313       }
       
  1314 
       
  1315       else if (png_ptr->screen_gamma != 0)
       
  1316          /* The converse - assume the file matches the screen, note that this
       
  1317           * perhaps undesireable default can (from 1.5.4) be changed by calling
       
  1318           * png_set_alpha_mode (even if the alpha handling mode isn't required
       
  1319           * or isn't changed from the default.)
       
  1320           */
       
  1321          png_ptr->gamma = png_reciprocal(png_ptr->screen_gamma);
       
  1322 
       
  1323       else /* neither are set */
       
  1324          /* Just in case the following prevents any processing - file and screen
       
  1325           * are both assumed to be linear and there is no way to introduce a
       
  1326           * third gamma value other than png_set_background with 'UNIQUE', and,
       
  1327           * prior to 1.5.4
       
  1328           */
       
  1329          png_ptr->screen_gamma = png_ptr->gamma = PNG_FP_1;
       
  1330 
       
  1331       /* Now turn the gamma transformation on or off as appropriate.  Notice
       
  1332        * that PNG_GAMMA just refers to the file->screen correction.  Alpha
       
  1333        * composition may independently cause gamma correction because it needs
       
  1334        * linear data (e.g. if the file has a gAMA chunk but the screen gamma
       
  1335        * hasn't been specified.)  In any case this flag may get turned off in
       
  1336        * the code immediately below if the transform can be handled outside the
       
  1337        * row loop.
       
  1338        */
       
  1339       if (gamma_correction)
       
  1340          png_ptr->transformations |= PNG_GAMMA;
       
  1341 
       
  1342       else
       
  1343          png_ptr->transformations &= ~PNG_GAMMA;
       
  1344    }
       
  1345 #endif
       
  1346 
       
  1347    /* Certain transformations have the effect of preventing other
       
  1348     * transformations that happen afterward in png_do_read_transformations,
       
  1349     * resolve the interdependencies here.  From the code of
       
  1350     * png_do_read_transformations the order is:
       
  1351     *
       
  1352     *  1) PNG_EXPAND (including PNG_EXPAND_tRNS)
       
  1353     *  2) PNG_STRIP_ALPHA (if no compose)
       
  1354     *  3) PNG_RGB_TO_GRAY
       
  1355     *  4) PNG_GRAY_TO_RGB iff !PNG_BACKGROUND_IS_GRAY
       
  1356     *  5) PNG_COMPOSE
       
  1357     *  6) PNG_GAMMA
       
  1358     *  7) PNG_STRIP_ALPHA (if compose)
       
  1359     *  8) PNG_ENCODE_ALPHA
       
  1360     *  9) PNG_SCALE_16_TO_8
       
  1361     * 10) PNG_16_TO_8
       
  1362     * 11) PNG_QUANTIZE (converts to palette)
       
  1363     * 12) PNG_EXPAND_16
       
  1364     * 13) PNG_GRAY_TO_RGB iff PNG_BACKGROUND_IS_GRAY
       
  1365     * 14) PNG_INVERT_MONO
       
  1366     * 15) PNG_SHIFT
       
  1367     * 16) PNG_PACK
       
  1368     * 17) PNG_BGR
       
  1369     * 18) PNG_PACKSWAP
       
  1370     * 19) PNG_FILLER (includes PNG_ADD_ALPHA)
       
  1371     * 20) PNG_INVERT_ALPHA
       
  1372     * 21) PNG_SWAP_ALPHA
       
  1373     * 22) PNG_SWAP_BYTES
       
  1374     * 23) PNG_USER_TRANSFORM [must be last]
       
  1375     */
       
  1376 #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
       
  1377    if ((png_ptr->transformations & PNG_STRIP_ALPHA) &&
       
  1378       !(png_ptr->transformations & PNG_COMPOSE))
       
  1379    {
       
  1380       /* Stripping the alpha channel happens immediately after the 'expand'
       
  1381        * transformations, before all other transformation, so it cancels out
       
  1382        * the alpha handling.  It has the side effect negating the effect of
       
  1383        * PNG_EXPAND_tRNS too:
       
  1384        */
       
  1385       png_ptr->transformations &= ~(PNG_BACKGROUND_EXPAND | PNG_ENCODE_ALPHA |
       
  1386          PNG_EXPAND_tRNS);
       
  1387       png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
       
  1388 
       
  1389       /* Kill the tRNS chunk itself too.  Prior to 1.5.4 this did not happen
       
  1390        * so transparency information would remain just so long as it wasn't
       
  1391        * expanded.  This produces unexpected API changes if the set of things
       
  1392        * that do PNG_EXPAND_tRNS changes (perfectly possible given the
       
  1393        * documentation - which says ask for what you want, accept what you
       
  1394        * get.)  This makes the behavior consistent from 1.5.4:
       
  1395        */
       
  1396       png_ptr->num_trans = 0;
       
  1397    }
       
  1398 #endif /* STRIP_ALPHA supported, no COMPOSE */
       
  1399 
       
  1400 #ifdef PNG_READ_ALPHA_MODE_SUPPORTED
       
  1401    /* If the screen gamma is about 1.0 then the OPTIMIZE_ALPHA and ENCODE_ALPHA
       
  1402     * settings will have no effect.
       
  1403     */
       
  1404    if (!png_gamma_significant(png_ptr->screen_gamma))
       
  1405    {
       
  1406       png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
       
  1407       png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
       
  1408    }
       
  1409 #endif
       
  1410 
       
  1411 #if defined(PNG_READ_EXPAND_SUPPORTED) && \
       
  1412    defined(PNG_READ_BACKGROUND_SUPPORTED) && \
       
  1413    defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
       
  1414    /* Detect gray background and attempt to enable optimization for
       
  1415     * gray --> RGB case.
       
  1416     *
       
  1417     * Note:  if PNG_BACKGROUND_EXPAND is set and color_type is either RGB or
       
  1418     * RGB_ALPHA (in which case need_expand is superfluous anyway), the
       
  1419     * background color might actually be gray yet not be flagged as such.
       
  1420     * This is not a problem for the current code, which uses
       
  1421     * PNG_BACKGROUND_IS_GRAY only to decide when to do the
       
  1422     * png_do_gray_to_rgb() transformation.
       
  1423     *
       
  1424     * TODO: this code needs to be revised to avoid the complexity and
       
  1425     * interdependencies.  The color type of the background should be recorded in
       
  1426     * png_set_background, along with the bit depth, then the code has a record
       
  1427     * of exactly what color space the background is currently in.
       
  1428     */
       
  1429    if (png_ptr->transformations & PNG_BACKGROUND_EXPAND)
       
  1430    {
       
  1431       /* PNG_BACKGROUND_EXPAND: the background is in the file color space, so if
       
  1432        * the file was greyscale the background value is gray.
       
  1433        */
       
  1434       if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR))
       
  1435          png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
       
  1436    }
       
  1437 
       
  1438    else if (png_ptr->transformations & PNG_COMPOSE)
       
  1439    {
       
  1440       /* PNG_COMPOSE: png_set_background was called with need_expand false,
       
  1441        * so the color is in the color space of the output or png_set_alpha_mode
       
  1442        * was called and the color is black.  Ignore RGB_TO_GRAY because that
       
  1443        * happens before GRAY_TO_RGB.
       
  1444        */
       
  1445       if (png_ptr->transformations & PNG_GRAY_TO_RGB)
       
  1446       {
       
  1447          if (png_ptr->background.red == png_ptr->background.green &&
       
  1448              png_ptr->background.red == png_ptr->background.blue)
       
  1449          {
       
  1450             png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
       
  1451             png_ptr->background.gray = png_ptr->background.red;
       
  1452          }
       
  1453       }
       
  1454    }
       
  1455 #endif /* PNG_READ_GRAY_TO_RGB_SUPPORTED (etc) */
       
  1456 
       
  1457    /* For indexed PNG data (PNG_COLOR_TYPE_PALETTE) many of the transformations
       
  1458     * can be performed directly on the palette, and some (such as rgb to gray)
       
  1459     * can be optimized inside the palette.  This is particularly true of the
       
  1460     * composite (background and alpha) stuff, which can be pretty much all done
       
  1461     * in the palette even if the result is expanded to RGB or gray afterward.
       
  1462     *
       
  1463     * NOTE: this is Not Yet Implemented, the code behaves as in 1.5.1 and
       
  1464     * earlier and the palette stuff is actually handled on the first row.  This
       
  1465     * leads to the reported bug that the palette returned by png_get_PLTE is not
       
  1466     * updated.
       
  1467     */
       
  1468    if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
       
  1469       png_init_palette_transformations(png_ptr);
       
  1470 
       
  1471    else
       
  1472       png_init_rgb_transformations(png_ptr);
       
  1473 
       
  1474 #if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
       
  1475    defined(PNG_READ_EXPAND_16_SUPPORTED)
       
  1476    if ((png_ptr->transformations & PNG_EXPAND_16) &&
       
  1477       (png_ptr->transformations & PNG_COMPOSE) &&
       
  1478       !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
       
  1479       png_ptr->bit_depth != 16)
       
  1480    {
       
  1481       /* TODO: fix this.  Because the expand_16 operation is after the compose
       
  1482        * handling the background color must be 8, not 16, bits deep, but the
       
  1483        * application will supply a 16-bit value so reduce it here.
       
  1484        *
       
  1485        * The PNG_BACKGROUND_EXPAND code above does not expand to 16 bits at
       
  1486        * present, so that case is ok (until do_expand_16 is moved.)
       
  1487        *
       
  1488        * NOTE: this discards the low 16 bits of the user supplied background
       
  1489        * color, but until expand_16 works properly there is no choice!
       
  1490        */
       
  1491 #     define CHOP(x) (x)=((png_uint_16)(((png_uint_32)(x)*255+32895) >> 16))
       
  1492       CHOP(png_ptr->background.red);
       
  1493       CHOP(png_ptr->background.green);
       
  1494       CHOP(png_ptr->background.blue);
       
  1495       CHOP(png_ptr->background.gray);
       
  1496 #     undef CHOP
       
  1497    }
       
  1498 #endif /* PNG_READ_BACKGROUND_SUPPORTED && PNG_READ_EXPAND_16_SUPPORTED */
       
  1499 
       
  1500    /* NOTE: below 'PNG_READ_ALPHA_MODE_SUPPORTED' is presumed to also enable the
       
  1501     * background support (see the comments in scripts/pnglibconf.dfa), this
       
  1502     * allows pre-multiplication of the alpha channel to be implemented as
       
  1503     * compositing on black.  This is probably sub-optimal and has been done in
       
  1504     * 1.5.4 betas simply to enable external critique and testing (i.e. to
       
  1505     * implement the new API quickly, without lots of internal changes.)
       
  1506     */
       
  1507 
       
  1508 #ifdef PNG_READ_GAMMA_SUPPORTED
       
  1509 #  ifdef PNG_READ_BACKGROUND_SUPPORTED
       
  1510       /* Includes ALPHA_MODE */
       
  1511       png_ptr->background_1 = png_ptr->background;
       
  1512 #  endif
       
  1513 
       
  1514    /* This needs to change - in the palette image case a whole set of tables are
       
  1515     * built when it would be quicker to just calculate the correct value for
       
  1516     * each palette entry directly.  Also, the test is too tricky - why check
       
  1517     * PNG_RGB_TO_GRAY if PNG_GAMMA is not set?  The answer seems to be that
       
  1518     * PNG_GAMMA is cancelled even if the gamma is known?  The test excludes the
       
  1519     * PNG_COMPOSE case, so apparently if there is no *overall* gamma correction
       
  1520     * the gamma tables will not be built even if composition is required on a
       
  1521     * gamma encoded value.
       
  1522     *
       
  1523     * In 1.5.4 this is addressed below by an additional check on the individual
       
  1524     * file gamma - if it is not 1.0 both RGB_TO_GRAY and COMPOSE need the
       
  1525     * tables.
       
  1526     */
       
  1527    if ((png_ptr->transformations & PNG_GAMMA)
       
  1528       || ((png_ptr->transformations & PNG_RGB_TO_GRAY)
       
  1529          && (png_gamma_significant(png_ptr->gamma) ||
       
  1530             png_gamma_significant(png_ptr->screen_gamma)))
       
  1531       || ((png_ptr->transformations & PNG_COMPOSE)
       
  1532          && (png_gamma_significant(png_ptr->gamma)
       
  1533             || png_gamma_significant(png_ptr->screen_gamma)
       
  1534 #  ifdef PNG_READ_BACKGROUND_SUPPORTED
       
  1535             || (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_UNIQUE
       
  1536                && png_gamma_significant(png_ptr->background_gamma))
       
  1537 #  endif
       
  1538       )) || ((png_ptr->transformations & PNG_ENCODE_ALPHA)
       
  1539          && png_gamma_significant(png_ptr->screen_gamma))
       
  1540       )
       
  1541    {
       
  1542       png_build_gamma_table(png_ptr, png_ptr->bit_depth);
       
  1543 
       
  1544 #ifdef PNG_READ_BACKGROUND_SUPPORTED
       
  1545       if (png_ptr->transformations & PNG_COMPOSE)
       
  1546       {
       
  1547          if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
       
  1548          {
       
  1549             /* We don't get to here unless there is a tRNS chunk with non-opaque
       
  1550              * entries - see the checking code at the start of this function.
       
  1551              */
       
  1552             png_color back, back_1;
       
  1553             png_colorp palette = png_ptr->palette;
       
  1554             int num_palette = png_ptr->num_palette;
       
  1555             int i;
       
  1556             if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
       
  1557             {
       
  1558 
       
  1559                back.red = png_ptr->gamma_table[png_ptr->background.red];
       
  1560                back.green = png_ptr->gamma_table[png_ptr->background.green];
       
  1561                back.blue = png_ptr->gamma_table[png_ptr->background.blue];
       
  1562 
       
  1563                back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
       
  1564                back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
       
  1565                back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
       
  1566             }
       
  1567             else
       
  1568             {
       
  1569                png_fixed_point g, gs;
       
  1570 
       
  1571                switch (png_ptr->background_gamma_type)
       
  1572                {
       
  1573                   case PNG_BACKGROUND_GAMMA_SCREEN:
       
  1574                      g = (png_ptr->screen_gamma);
       
  1575                      gs = PNG_FP_1;
       
  1576                      break;
       
  1577 
       
  1578                   case PNG_BACKGROUND_GAMMA_FILE:
       
  1579                      g = png_reciprocal(png_ptr->gamma);
       
  1580                      gs = png_reciprocal2(png_ptr->gamma,
       
  1581                         png_ptr->screen_gamma);
       
  1582                      break;
       
  1583 
       
  1584                   case PNG_BACKGROUND_GAMMA_UNIQUE:
       
  1585                      g = png_reciprocal(png_ptr->background_gamma);
       
  1586                      gs = png_reciprocal2(png_ptr->background_gamma,
       
  1587                         png_ptr->screen_gamma);
       
  1588                      break;
       
  1589                   default:
       
  1590                      g = PNG_FP_1;    /* back_1 */
       
  1591                      gs = PNG_FP_1;   /* back */
       
  1592                      break;
       
  1593                }
       
  1594 
       
  1595                if (png_gamma_significant(gs))
       
  1596                {
       
  1597                   back.red = png_gamma_8bit_correct(png_ptr->background.red,
       
  1598                       gs);
       
  1599                   back.green = png_gamma_8bit_correct(png_ptr->background.green,
       
  1600                       gs);
       
  1601                   back.blue = png_gamma_8bit_correct(png_ptr->background.blue,
       
  1602                       gs);
       
  1603                }
       
  1604 
       
  1605                else
       
  1606                {
       
  1607                   back.red   = (png_byte)png_ptr->background.red;
       
  1608                   back.green = (png_byte)png_ptr->background.green;
       
  1609                   back.blue  = (png_byte)png_ptr->background.blue;
       
  1610                }
       
  1611 
       
  1612                if (png_gamma_significant(g))
       
  1613                {
       
  1614                   back_1.red = png_gamma_8bit_correct(png_ptr->background.red,
       
  1615                      g);
       
  1616                   back_1.green = png_gamma_8bit_correct(
       
  1617                      png_ptr->background.green, g);
       
  1618                   back_1.blue = png_gamma_8bit_correct(png_ptr->background.blue,
       
  1619                      g);
       
  1620                }
       
  1621 
       
  1622                else
       
  1623                {
       
  1624                   back_1.red   = (png_byte)png_ptr->background.red;
       
  1625                   back_1.green = (png_byte)png_ptr->background.green;
       
  1626                   back_1.blue  = (png_byte)png_ptr->background.blue;
       
  1627                }
       
  1628             }
       
  1629 
       
  1630             for (i = 0; i < num_palette; i++)
       
  1631             {
       
  1632                if (i < (int)png_ptr->num_trans &&
       
  1633                    png_ptr->trans_alpha[i] != 0xff)
       
  1634                {
       
  1635                   if (png_ptr->trans_alpha[i] == 0)
       
  1636                   {
       
  1637                      palette[i] = back;
       
  1638                   }
       
  1639                   else /* if (png_ptr->trans_alpha[i] != 0xff) */
       
  1640                   {
       
  1641                      png_byte v, w;
       
  1642 
       
  1643                      v = png_ptr->gamma_to_1[palette[i].red];
       
  1644                      png_composite(w, v, png_ptr->trans_alpha[i], back_1.red);
       
  1645                      palette[i].red = png_ptr->gamma_from_1[w];
       
  1646 
       
  1647                      v = png_ptr->gamma_to_1[palette[i].green];
       
  1648                      png_composite(w, v, png_ptr->trans_alpha[i], back_1.green);
       
  1649                      palette[i].green = png_ptr->gamma_from_1[w];
       
  1650 
       
  1651                      v = png_ptr->gamma_to_1[palette[i].blue];
       
  1652                      png_composite(w, v, png_ptr->trans_alpha[i], back_1.blue);
       
  1653                      palette[i].blue = png_ptr->gamma_from_1[w];
       
  1654                   }
       
  1655                }
       
  1656                else
       
  1657                {
       
  1658                   palette[i].red = png_ptr->gamma_table[palette[i].red];
       
  1659                   palette[i].green = png_ptr->gamma_table[palette[i].green];
       
  1660                   palette[i].blue = png_ptr->gamma_table[palette[i].blue];
       
  1661                }
       
  1662             }
       
  1663 
       
  1664             /* Prevent the transformations being done again.
       
  1665              *
       
  1666              * NOTE: this is highly dubious; it zaps the transformations in
       
  1667              * place.  This seems inconsistent with the general treatment of the
       
  1668              * transformations elsewhere.
       
  1669              */
       
  1670             png_ptr->transformations &= ~(PNG_COMPOSE | PNG_GAMMA);
       
  1671          } /* color_type == PNG_COLOR_TYPE_PALETTE */
       
  1672 
       
  1673          /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */
       
  1674          else /* color_type != PNG_COLOR_TYPE_PALETTE */
       
  1675          {
       
  1676             png_fixed_point g = PNG_FP_1;
       
  1677             png_fixed_point gs = PNG_FP_1;
       
  1678 
       
  1679             switch (png_ptr->background_gamma_type)
       
  1680             {
       
  1681                case PNG_BACKGROUND_GAMMA_SCREEN:
       
  1682                   g = png_ptr->screen_gamma;
       
  1683                   /* gs = PNG_FP_1; */
       
  1684                   break;
       
  1685 
       
  1686                case PNG_BACKGROUND_GAMMA_FILE:
       
  1687                   g = png_reciprocal(png_ptr->gamma);
       
  1688                   gs = png_reciprocal2(png_ptr->gamma, png_ptr->screen_gamma);
       
  1689                   break;
       
  1690 
       
  1691                case PNG_BACKGROUND_GAMMA_UNIQUE:
       
  1692                   g = png_reciprocal(png_ptr->background_gamma);
       
  1693                   gs = png_reciprocal2(png_ptr->background_gamma,
       
  1694                       png_ptr->screen_gamma);
       
  1695                   break;
       
  1696 
       
  1697                default:
       
  1698                   png_error(png_ptr, "invalid background gamma type");
       
  1699             }
       
  1700 
       
  1701             png_ptr->background_1.gray = png_gamma_correct(png_ptr,
       
  1702                 png_ptr->background.gray, g);
       
  1703 
       
  1704             png_ptr->background.gray = png_gamma_correct(png_ptr,
       
  1705                 png_ptr->background.gray, gs);
       
  1706 
       
  1707             if ((png_ptr->background.red != png_ptr->background.green) ||
       
  1708                 (png_ptr->background.red != png_ptr->background.blue) ||
       
  1709                 (png_ptr->background.red != png_ptr->background.gray))
       
  1710             {
       
  1711                /* RGB or RGBA with color background */
       
  1712                png_ptr->background_1.red = png_gamma_correct(png_ptr,
       
  1713                    png_ptr->background.red, g);
       
  1714 
       
  1715                png_ptr->background_1.green = png_gamma_correct(png_ptr,
       
  1716                    png_ptr->background.green, g);
       
  1717 
       
  1718                png_ptr->background_1.blue = png_gamma_correct(png_ptr,
       
  1719                    png_ptr->background.blue, g);
       
  1720 
       
  1721                png_ptr->background.red = png_gamma_correct(png_ptr,
       
  1722                    png_ptr->background.red, gs);
       
  1723 
       
  1724                png_ptr->background.green = png_gamma_correct(png_ptr,
       
  1725                    png_ptr->background.green, gs);
       
  1726 
       
  1727                png_ptr->background.blue = png_gamma_correct(png_ptr,
       
  1728                    png_ptr->background.blue, gs);
       
  1729             }
       
  1730 
       
  1731             else
       
  1732             {
       
  1733                /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */
       
  1734                png_ptr->background_1.red = png_ptr->background_1.green
       
  1735                    = png_ptr->background_1.blue = png_ptr->background_1.gray;
       
  1736 
       
  1737                png_ptr->background.red = png_ptr->background.green
       
  1738                    = png_ptr->background.blue = png_ptr->background.gray;
       
  1739             }
       
  1740          } /* color_type != PNG_COLOR_TYPE_PALETTE */
       
  1741       }/* png_ptr->transformations & PNG_BACKGROUND */
       
  1742 
       
  1743       else
       
  1744       /* Transformation does not include PNG_BACKGROUND */
       
  1745 #endif /* PNG_READ_BACKGROUND_SUPPORTED */
       
  1746       if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
       
  1747       {
       
  1748          png_colorp palette = png_ptr->palette;
       
  1749          int num_palette = png_ptr->num_palette;
       
  1750          int i;
       
  1751 
       
  1752          /*NOTE: there are other transformations that should probably be in here
       
  1753           * too.
       
  1754           */
       
  1755          for (i = 0; i < num_palette; i++)
       
  1756          {
       
  1757             palette[i].red = png_ptr->gamma_table[palette[i].red];
       
  1758             palette[i].green = png_ptr->gamma_table[palette[i].green];
       
  1759             palette[i].blue = png_ptr->gamma_table[palette[i].blue];
       
  1760          }
       
  1761 
       
  1762          /* Done the gamma correction. */
       
  1763          png_ptr->transformations &= ~PNG_GAMMA;
       
  1764       } /* color_type == PALETTE && !PNG_BACKGROUND transformation */
       
  1765    }
       
  1766 #ifdef PNG_READ_BACKGROUND_SUPPORTED
       
  1767    else
       
  1768 #endif
       
  1769 #endif /* PNG_READ_GAMMA_SUPPORTED */
       
  1770 
       
  1771 #ifdef PNG_READ_BACKGROUND_SUPPORTED
       
  1772    /* No GAMMA transformation (see the hanging else 4 lines above) */
       
  1773    if ((png_ptr->transformations & PNG_COMPOSE) &&
       
  1774        (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))
       
  1775    {
       
  1776       int i;
       
  1777       int istop = (int)png_ptr->num_trans;
       
  1778       png_color back;
       
  1779       png_colorp palette = png_ptr->palette;
       
  1780 
       
  1781       back.red   = (png_byte)png_ptr->background.red;
       
  1782       back.green = (png_byte)png_ptr->background.green;
       
  1783       back.blue  = (png_byte)png_ptr->background.blue;
       
  1784 
       
  1785       for (i = 0; i < istop; i++)
       
  1786       {
       
  1787          if (png_ptr->trans_alpha[i] == 0)
       
  1788          {
       
  1789             palette[i] = back;
       
  1790          }
       
  1791 
       
  1792          else if (png_ptr->trans_alpha[i] != 0xff)
       
  1793          {
       
  1794             /* The png_composite() macro is defined in png.h */
       
  1795             png_composite(palette[i].red, palette[i].red,
       
  1796                 png_ptr->trans_alpha[i], back.red);
       
  1797 
       
  1798             png_composite(palette[i].green, palette[i].green,
       
  1799                 png_ptr->trans_alpha[i], back.green);
       
  1800 
       
  1801             png_composite(palette[i].blue, palette[i].blue,
       
  1802                 png_ptr->trans_alpha[i], back.blue);
       
  1803          }
       
  1804       }
       
  1805 
       
  1806       png_ptr->transformations &= ~PNG_COMPOSE;
       
  1807    }
       
  1808 #endif /* PNG_READ_BACKGROUND_SUPPORTED */
       
  1809 
       
  1810 #ifdef PNG_READ_SHIFT_SUPPORTED
       
  1811    if ((png_ptr->transformations & PNG_SHIFT) &&
       
  1812        (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))
       
  1813    {
       
  1814       png_uint_16 i;
       
  1815       png_uint_16 istop = png_ptr->num_palette;
       
  1816       int sr = 8 - png_ptr->sig_bit.red;
       
  1817       int sg = 8 - png_ptr->sig_bit.green;
       
  1818       int sb = 8 - png_ptr->sig_bit.blue;
       
  1819 
       
  1820       if (sr < 0 || sr > 8)
       
  1821          sr = 0;
       
  1822 
       
  1823       if (sg < 0 || sg > 8)
       
  1824          sg = 0;
       
  1825 
       
  1826       if (sb < 0 || sb > 8)
       
  1827          sb = 0;
       
  1828 
       
  1829       for (i = 0; i < istop; i++)
       
  1830       {
       
  1831          png_ptr->palette[i].red >>= sr;
       
  1832          png_ptr->palette[i].green >>= sg;
       
  1833          png_ptr->palette[i].blue >>= sb;
       
  1834       }
       
  1835    }
       
  1836 #endif  /* PNG_READ_SHIFT_SUPPORTED */
       
  1837 }
       
  1838 
       
  1839 /* Modify the info structure to reflect the transformations.  The
       
  1840  * info should be updated so a PNG file could be written with it,
       
  1841  * assuming the transformations result in valid PNG data.
       
  1842  */
       
  1843 void /* PRIVATE */
       
  1844 png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
       
  1845 {
       
  1846    png_debug(1, "in png_read_transform_info");
       
  1847 
       
  1848 #ifdef PNG_READ_EXPAND_SUPPORTED
       
  1849    if (png_ptr->transformations & PNG_EXPAND)
       
  1850    {
       
  1851       if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
       
  1852       {
       
  1853          /* This check must match what actually happens in
       
  1854           * png_do_expand_palette; if it ever checks the tRNS chunk to see if
       
  1855           * it is all opaque we must do the same (at present it does not.)
       
  1856           */
       
  1857          if (png_ptr->num_trans > 0)
       
  1858             info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
       
  1859 
       
  1860          else
       
  1861             info_ptr->color_type = PNG_COLOR_TYPE_RGB;
       
  1862 
       
  1863          info_ptr->bit_depth = 8;
       
  1864          info_ptr->num_trans = 0;
       
  1865 
       
  1866          if (png_ptr->palette == NULL)
       
  1867             png_error (png_ptr, "Palette is NULL in indexed image");
       
  1868       }
       
  1869       else
       
  1870       {
       
  1871          if (png_ptr->num_trans)
       
  1872          {
       
  1873             if (png_ptr->transformations & PNG_EXPAND_tRNS)
       
  1874                info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
       
  1875          }
       
  1876          if (info_ptr->bit_depth < 8)
       
  1877             info_ptr->bit_depth = 8;
       
  1878 
       
  1879          info_ptr->num_trans = 0;
       
  1880       }
       
  1881    }
       
  1882 #endif
       
  1883 
       
  1884 #if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
       
  1885    defined(PNG_READ_ALPHA_MODE_SUPPORTED)
       
  1886    /* The following is almost certainly wrong unless the background value is in
       
  1887     * the screen space!
       
  1888     */
       
  1889    if (png_ptr->transformations & PNG_COMPOSE)
       
  1890       info_ptr->background = png_ptr->background;
       
  1891 #endif
       
  1892 
       
  1893 #ifdef PNG_READ_GAMMA_SUPPORTED
       
  1894    /* The following used to be conditional on PNG_GAMMA (prior to 1.5.4),
       
  1895     * however it seems that the code in png_init_read_transformations, which has
       
  1896     * been called before this from png_read_update_info->png_read_start_row
       
  1897     * sometimes does the gamma transform and cancels the flag.
       
  1898     */
       
  1899    info_ptr->gamma = png_ptr->gamma;
       
  1900 #endif
       
  1901 
       
  1902    if (info_ptr->bit_depth == 16)
       
  1903    {
       
  1904 #  ifdef PNG_READ_16BIT_SUPPORTED
       
  1905 #     ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
       
  1906          if (png_ptr->transformations & PNG_SCALE_16_TO_8)
       
  1907             info_ptr->bit_depth = 8;
       
  1908 #     endif
       
  1909 
       
  1910 #     ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
       
  1911          if (png_ptr->transformations & PNG_16_TO_8)
       
  1912             info_ptr->bit_depth = 8;
       
  1913 #     endif
       
  1914 
       
  1915 #  else
       
  1916       /* No 16 bit support: force chopping 16-bit input down to 8, in this case
       
  1917        * the app program can chose if both APIs are available by setting the
       
  1918        * correct scaling to use.
       
  1919        */
       
  1920 #     ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
       
  1921          /* For compatibility with previous versions use the strip method by
       
  1922           * default.  This code works because if PNG_SCALE_16_TO_8 is already
       
  1923           * set the code below will do that in preference to the chop.
       
  1924           */
       
  1925          png_ptr->transformations |= PNG_16_TO_8;
       
  1926          info_ptr->bit_depth = 8;
       
  1927 #     else
       
  1928 
       
  1929 #        if PNG_READ_SCALE_16_TO_8_SUPPORTED
       
  1930             png_ptr->transformations |= PNG_SCALE_16_TO_8;
       
  1931             info_ptr->bit_depth = 8;
       
  1932 #        else
       
  1933 
       
  1934             CONFIGURATION ERROR: you must enable at least one 16 to 8 method
       
  1935 #        endif
       
  1936 #    endif
       
  1937 #endif /* !READ_16BIT_SUPPORTED */
       
  1938    }
       
  1939 
       
  1940 #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
       
  1941    if (png_ptr->transformations & PNG_GRAY_TO_RGB)
       
  1942       info_ptr->color_type |= PNG_COLOR_MASK_COLOR;
       
  1943 #endif
       
  1944 
       
  1945 #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
       
  1946    if (png_ptr->transformations & PNG_RGB_TO_GRAY)
       
  1947       info_ptr->color_type &= ~PNG_COLOR_MASK_COLOR;
       
  1948 #endif
       
  1949 
       
  1950 #ifdef PNG_READ_QUANTIZE_SUPPORTED
       
  1951    if (png_ptr->transformations & PNG_QUANTIZE)
       
  1952    {
       
  1953       if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
       
  1954           (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) &&
       
  1955           png_ptr->palette_lookup && info_ptr->bit_depth == 8)
       
  1956       {
       
  1957          info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
       
  1958       }
       
  1959    }
       
  1960 #endif
       
  1961 
       
  1962 #ifdef PNG_READ_EXPAND_16_SUPPORTED
       
  1963    if (png_ptr->transformations & PNG_EXPAND_16 && info_ptr->bit_depth == 8 &&
       
  1964       info_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
       
  1965    {
       
  1966       info_ptr->bit_depth = 16;
       
  1967    }
       
  1968 #endif
       
  1969 
       
  1970 #ifdef PNG_READ_PACK_SUPPORTED
       
  1971    if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8))
       
  1972       info_ptr->bit_depth = 8;
       
  1973 #endif
       
  1974 
       
  1975    if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
       
  1976       info_ptr->channels = 1;
       
  1977 
       
  1978    else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
       
  1979       info_ptr->channels = 3;
       
  1980 
       
  1981    else
       
  1982       info_ptr->channels = 1;
       
  1983 
       
  1984 #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
       
  1985    if (png_ptr->transformations & PNG_STRIP_ALPHA)
       
  1986    {
       
  1987       info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
       
  1988       info_ptr->num_trans = 0;
       
  1989    }
       
  1990 #endif
       
  1991 
       
  1992    if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
       
  1993       info_ptr->channels++;
       
  1994 
       
  1995 #ifdef PNG_READ_FILLER_SUPPORTED
       
  1996    /* STRIP_ALPHA and FILLER allowed:  MASK_ALPHA bit stripped above */
       
  1997    if ((png_ptr->transformations & PNG_FILLER) &&
       
  1998        ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
       
  1999        (info_ptr->color_type == PNG_COLOR_TYPE_GRAY)))
       
  2000    {
       
  2001       info_ptr->channels++;
       
  2002       /* If adding a true alpha channel not just filler */
       
  2003       if (png_ptr->transformations & PNG_ADD_ALPHA)
       
  2004          info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
       
  2005    }
       
  2006 #endif
       
  2007 
       
  2008 #if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \
       
  2009 defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
       
  2010    if (png_ptr->transformations & PNG_USER_TRANSFORM)
       
  2011    {
       
  2012       if (info_ptr->bit_depth < png_ptr->user_transform_depth)
       
  2013          info_ptr->bit_depth = png_ptr->user_transform_depth;
       
  2014 
       
  2015       if (info_ptr->channels < png_ptr->user_transform_channels)
       
  2016          info_ptr->channels = png_ptr->user_transform_channels;
       
  2017    }
       
  2018 #endif
       
  2019 
       
  2020    info_ptr->pixel_depth = (png_byte)(info_ptr->channels *
       
  2021        info_ptr->bit_depth);
       
  2022 
       
  2023    info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, info_ptr->width);
       
  2024 
       
  2025    /* Adding in 1.5.4: cache the above value in png_struct so that we can later
       
  2026     * check in png_rowbytes that the user buffer won't get overwritten.  Note
       
  2027     * that the field is not always set - if png_read_update_info isn't called
       
  2028     * the application has to either not do any transforms or get the calculation
       
  2029     * right itself.
       
  2030     */
       
  2031    png_ptr->info_rowbytes = info_ptr->rowbytes;
       
  2032 
       
  2033 #ifndef PNG_READ_EXPAND_SUPPORTED
       
  2034    if (png_ptr)
       
  2035       return;
       
  2036 #endif
       
  2037 }
       
  2038 
       
  2039 /* Transform the row.  The order of transformations is significant,
       
  2040  * and is very touchy.  If you add a transformation, take care to
       
  2041  * decide how it fits in with the other transformations here.
       
  2042  */
       
  2043 void /* PRIVATE */
       
  2044 png_do_read_transformations(png_structp png_ptr)
       
  2045 {
       
  2046    png_debug(1, "in png_do_read_transformations");
       
  2047 
       
  2048    if (png_ptr->row_buf == NULL)
       
  2049    {
       
  2050       /* Prior to 1.5.4 this output row/pass where the NULL pointer is, but this
       
  2051        * error is incredibly rare and incredibly easy to debug without this
       
  2052        * information.
       
  2053        */
       
  2054       png_error(png_ptr, "NULL row buffer");
       
  2055    }
       
  2056 
       
  2057    /* The following is debugging; prior to 1.5.4 the code was never compiled in;
       
  2058     * in 1.5.4 PNG_FLAG_DETECT_UNINITIALIZED was added and the macro
       
  2059     * PNG_WARN_UNINITIALIZED_ROW removed.  In 1.5 the new flag is set only for
       
  2060     * selected new APIs to ensure that there is no API change.
       
  2061     */
       
  2062    if ((png_ptr->flags & PNG_FLAG_DETECT_UNINITIALIZED) != 0 &&
       
  2063       !(png_ptr->flags & PNG_FLAG_ROW_INIT))
       
  2064    {
       
  2065       /* Application has failed to call either png_read_start_image() or
       
  2066        * png_read_update_info() after setting transforms that expand pixels.
       
  2067        * This check added to libpng-1.2.19 (but not enabled until 1.5.4).
       
  2068        */
       
  2069       png_error(png_ptr, "Uninitialized row");
       
  2070    }
       
  2071 
       
  2072 #ifdef PNG_READ_EXPAND_SUPPORTED
       
  2073    if (png_ptr->transformations & PNG_EXPAND)
       
  2074    {
       
  2075       if (png_ptr->row_info.color_type == PNG_COLOR_TYPE_PALETTE)
       
  2076       {
       
  2077          png_do_expand_palette(&(png_ptr->row_info), png_ptr->row_buf + 1,
       
  2078              png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans);
       
  2079       }
       
  2080 
       
  2081       else
       
  2082       {
       
  2083          if (png_ptr->num_trans &&
       
  2084              (png_ptr->transformations & PNG_EXPAND_tRNS))
       
  2085             png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
       
  2086                 &(png_ptr->trans_color));
       
  2087 
       
  2088          else
       
  2089             png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
       
  2090                 NULL);
       
  2091       }
       
  2092    }
       
  2093 #endif
       
  2094 
       
  2095 #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
       
  2096    if ((png_ptr->transformations & PNG_STRIP_ALPHA) &&
       
  2097       !(png_ptr->transformations & PNG_COMPOSE) &&
       
  2098       (png_ptr->row_info.color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
       
  2099       png_ptr->row_info.color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
       
  2100       png_do_strip_channel(&(png_ptr->row_info), png_ptr->row_buf + 1,
       
  2101          0 /* at_start == false, because SWAP_ALPHA happens later */);
       
  2102 #endif
       
  2103 
       
  2104 #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
       
  2105    if (png_ptr->transformations & PNG_RGB_TO_GRAY)
       
  2106    {
       
  2107       int rgb_error =
       
  2108           png_do_rgb_to_gray(png_ptr, &(png_ptr->row_info),
       
  2109               png_ptr->row_buf + 1);
       
  2110 
       
  2111       if (rgb_error)
       
  2112       {
       
  2113          png_ptr->rgb_to_gray_status=1;
       
  2114          if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
       
  2115              PNG_RGB_TO_GRAY_WARN)
       
  2116             png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel");
       
  2117 
       
  2118          if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
       
  2119              PNG_RGB_TO_GRAY_ERR)
       
  2120             png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel");
       
  2121       }
       
  2122    }
       
  2123 #endif
       
  2124 
       
  2125 /* From Andreas Dilger e-mail to png-implement, 26 March 1998:
       
  2126  *
       
  2127  *   In most cases, the "simple transparency" should be done prior to doing
       
  2128  *   gray-to-RGB, or you will have to test 3x as many bytes to check if a
       
  2129  *   pixel is transparent.  You would also need to make sure that the
       
  2130  *   transparency information is upgraded to RGB.
       
  2131  *
       
  2132  *   To summarize, the current flow is:
       
  2133  *   - Gray + simple transparency -> compare 1 or 2 gray bytes and composite
       
  2134  *                                   with background "in place" if transparent,
       
  2135  *                                   convert to RGB if necessary
       
  2136  *   - Gray + alpha -> composite with gray background and remove alpha bytes,
       
  2137  *                                   convert to RGB if necessary
       
  2138  *
       
  2139  *   To support RGB backgrounds for gray images we need:
       
  2140  *   - Gray + simple transparency -> convert to RGB + simple transparency,
       
  2141  *                                   compare 3 or 6 bytes and composite with
       
  2142  *                                   background "in place" if transparent
       
  2143  *                                   (3x compare/pixel compared to doing
       
  2144  *                                   composite with gray bkgrnd)
       
  2145  *   - Gray + alpha -> convert to RGB + alpha, composite with background and
       
  2146  *                                   remove alpha bytes (3x float
       
  2147  *                                   operations/pixel compared with composite
       
  2148  *                                   on gray background)
       
  2149  *
       
  2150  *  Greg's change will do this.  The reason it wasn't done before is for
       
  2151  *  performance, as this increases the per-pixel operations.  If we would check
       
  2152  *  in advance if the background was gray or RGB, and position the gray-to-RGB
       
  2153  *  transform appropriately, then it would save a lot of work/time.
       
  2154  */
       
  2155 
       
  2156 #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
       
  2157    /* If gray -> RGB, do so now only if background is non-gray; else do later
       
  2158     * for performance reasons
       
  2159     */
       
  2160    if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
       
  2161        !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
       
  2162       png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
       
  2163 #endif
       
  2164 
       
  2165 #if (defined PNG_READ_BACKGROUND_SUPPORTED) ||\
       
  2166    (defined PNG_READ_ALPHA_MODE_SUPPORTED)
       
  2167    if (png_ptr->transformations & PNG_COMPOSE)
       
  2168       png_do_compose(&(png_ptr->row_info), png_ptr->row_buf + 1, png_ptr);
       
  2169 #endif
       
  2170 
       
  2171 #ifdef PNG_READ_GAMMA_SUPPORTED
       
  2172    if ((png_ptr->transformations & PNG_GAMMA) &&
       
  2173 #if (defined PNG_READ_BACKGROUND_SUPPORTED) ||\
       
  2174    (defined PNG_READ_ALPHA_MODE_SUPPORTED)
       
  2175        !((png_ptr->transformations & PNG_COMPOSE) &&
       
  2176        ((png_ptr->num_trans != 0) ||
       
  2177        (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) &&
       
  2178 #endif
       
  2179        (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE))
       
  2180       png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1, png_ptr);
       
  2181 #endif
       
  2182 
       
  2183 #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
       
  2184    if ((png_ptr->transformations & PNG_STRIP_ALPHA) &&
       
  2185       (png_ptr->transformations & PNG_COMPOSE) &&
       
  2186       (png_ptr->row_info.color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
       
  2187       png_ptr->row_info.color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
       
  2188       png_do_strip_channel(&(png_ptr->row_info), png_ptr->row_buf + 1,
       
  2189          0 /* at_start == false, because SWAP_ALPHA happens later */);
       
  2190 #endif
       
  2191 
       
  2192 #ifdef PNG_READ_ALPHA_MODE_SUPPORTED
       
  2193    if ((png_ptr->transformations & PNG_ENCODE_ALPHA) &&
       
  2194       (png_ptr->row_info.color_type & PNG_COLOR_MASK_ALPHA))
       
  2195       png_do_encode_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1, png_ptr);
       
  2196 #endif
       
  2197 
       
  2198 #ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
       
  2199    if (png_ptr->transformations & PNG_SCALE_16_TO_8)
       
  2200       png_do_scale_16_to_8(&(png_ptr->row_info), png_ptr->row_buf + 1);
       
  2201 #endif
       
  2202 
       
  2203 #ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
       
  2204    /* There is no harm in doing both of these because only one has any effect,
       
  2205     * by putting the 'scale' option first if the app asks for scale (either by
       
  2206     * calling the API or in a TRANSFORM flag) this is what happens.
       
  2207     */
       
  2208    if (png_ptr->transformations & PNG_16_TO_8)
       
  2209       png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1);
       
  2210 #endif
       
  2211 
       
  2212 #ifdef PNG_READ_QUANTIZE_SUPPORTED
       
  2213    if (png_ptr->transformations & PNG_QUANTIZE)
       
  2214    {
       
  2215       png_do_quantize(&(png_ptr->row_info), png_ptr->row_buf + 1,
       
  2216           png_ptr->palette_lookup, png_ptr->quantize_index);
       
  2217 
       
  2218       if (png_ptr->row_info.rowbytes == 0)
       
  2219          png_error(png_ptr, "png_do_quantize returned rowbytes=0");
       
  2220    }
       
  2221 #endif /* PNG_READ_QUANTIZE_SUPPORTED */
       
  2222 
       
  2223 #ifdef PNG_READ_EXPAND_16_SUPPORTED
       
  2224    /* Do the expansion now, after all the arithmetic has been done.  Notice
       
  2225     * that previous transformations can handle the PNG_EXPAND_16 flag if this
       
  2226     * is efficient (particularly true in the case of gamma correction, where
       
  2227     * better accuracy results faster!)
       
  2228     */
       
  2229    if (png_ptr->transformations & PNG_EXPAND_16)
       
  2230       png_do_expand_16(&png_ptr->row_info, png_ptr->row_buf + 1);
       
  2231 #endif
       
  2232 
       
  2233 #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
       
  2234    /*NOTE: moved here in 1.5.4 (from much later in this list.) */
       
  2235    if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
       
  2236        (png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
       
  2237       png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
       
  2238 #endif
       
  2239 
       
  2240 #ifdef PNG_READ_INVERT_SUPPORTED
       
  2241    if (png_ptr->transformations & PNG_INVERT_MONO)
       
  2242       png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1);
       
  2243 #endif
       
  2244 
       
  2245 #ifdef PNG_READ_SHIFT_SUPPORTED
       
  2246    if (png_ptr->transformations & PNG_SHIFT)
       
  2247       png_do_unshift(&(png_ptr->row_info), png_ptr->row_buf + 1,
       
  2248           &(png_ptr->shift));
       
  2249 #endif
       
  2250 
       
  2251 #ifdef PNG_READ_PACK_SUPPORTED
       
  2252    if (png_ptr->transformations & PNG_PACK)
       
  2253       png_do_unpack(&(png_ptr->row_info), png_ptr->row_buf + 1);
       
  2254 #endif
       
  2255 
       
  2256 #ifdef PNG_READ_BGR_SUPPORTED
       
  2257    if (png_ptr->transformations & PNG_BGR)
       
  2258       png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1);
       
  2259 #endif
       
  2260 
       
  2261 #ifdef PNG_READ_PACKSWAP_SUPPORTED
       
  2262    if (png_ptr->transformations & PNG_PACKSWAP)
       
  2263       png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1);
       
  2264 #endif
       
  2265 
       
  2266 #ifdef PNG_READ_FILLER_SUPPORTED
       
  2267    if (png_ptr->transformations & PNG_FILLER)
       
  2268       png_do_read_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
       
  2269           (png_uint_32)png_ptr->filler, png_ptr->flags);
       
  2270 #endif
       
  2271 
       
  2272 #ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
       
  2273    if (png_ptr->transformations & PNG_INVERT_ALPHA)
       
  2274       png_do_read_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
       
  2275 #endif
       
  2276 
       
  2277 #ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
       
  2278    if (png_ptr->transformations & PNG_SWAP_ALPHA)
       
  2279       png_do_read_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
       
  2280 #endif
       
  2281 
       
  2282 #ifdef PNG_READ_16BIT_SUPPORTED
       
  2283 #ifdef PNG_READ_SWAP_SUPPORTED
       
  2284    if (png_ptr->transformations & PNG_SWAP_BYTES)
       
  2285       png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1);
       
  2286 #endif
       
  2287 #endif
       
  2288 
       
  2289 #ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
       
  2290    if (png_ptr->transformations & PNG_USER_TRANSFORM)
       
  2291     {
       
  2292       if (png_ptr->read_user_transform_fn != NULL)
       
  2293          (*(png_ptr->read_user_transform_fn)) /* User read transform function */
       
  2294              (png_ptr,                    /* png_ptr */
       
  2295              &(png_ptr->row_info),     /* row_info: */
       
  2296                 /*  png_uint_32 width;       width of row */
       
  2297                 /*  png_size_t rowbytes;     number of bytes in row */
       
  2298                 /*  png_byte color_type;     color type of pixels */
       
  2299                 /*  png_byte bit_depth;      bit depth of samples */
       
  2300                 /*  png_byte channels;       number of channels (1-4) */
       
  2301                 /*  png_byte pixel_depth;    bits per pixel (depth*channels) */
       
  2302              png_ptr->row_buf + 1);    /* start of pixel data for row */
       
  2303 #ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
       
  2304       if (png_ptr->user_transform_depth)
       
  2305          png_ptr->row_info.bit_depth = png_ptr->user_transform_depth;
       
  2306 
       
  2307       if (png_ptr->user_transform_channels)
       
  2308          png_ptr->row_info.channels = png_ptr->user_transform_channels;
       
  2309 #endif
       
  2310       png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth *
       
  2311           png_ptr->row_info.channels);
       
  2312 
       
  2313       png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth,
       
  2314           png_ptr->row_info.width);
       
  2315    }
       
  2316 #endif
       
  2317 }
       
  2318 
       
  2319 #ifdef PNG_READ_PACK_SUPPORTED
       
  2320 /* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel,
       
  2321  * without changing the actual values.  Thus, if you had a row with
       
  2322  * a bit depth of 1, you would end up with bytes that only contained
       
  2323  * the numbers 0 or 1.  If you would rather they contain 0 and 255, use
       
  2324  * png_do_shift() after this.
       
  2325  */
       
  2326 void /* PRIVATE */
       
  2327 png_do_unpack(png_row_infop row_info, png_bytep row)
       
  2328 {
       
  2329    png_debug(1, "in png_do_unpack");
       
  2330 
       
  2331    if (row_info->bit_depth < 8)
       
  2332    {
       
  2333       png_uint_32 i;
       
  2334       png_uint_32 row_width=row_info->width;
       
  2335 
       
  2336       switch (row_info->bit_depth)
       
  2337       {
       
  2338          case 1:
       
  2339          {
       
  2340             png_bytep sp = row + (png_size_t)((row_width - 1) >> 3);
       
  2341             png_bytep dp = row + (png_size_t)row_width - 1;
       
  2342             png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07);
       
  2343             for (i = 0; i < row_width; i++)
       
  2344             {
       
  2345                *dp = (png_byte)((*sp >> shift) & 0x01);
       
  2346 
       
  2347                if (shift == 7)
       
  2348                {
       
  2349                   shift = 0;
       
  2350                   sp--;
       
  2351                }
       
  2352 
       
  2353                else
       
  2354                   shift++;
       
  2355 
       
  2356                dp--;
       
  2357             }
       
  2358             break;
       
  2359          }
       
  2360 
       
  2361          case 2:
       
  2362          {
       
  2363 
       
  2364             png_bytep sp = row + (png_size_t)((row_width - 1) >> 2);
       
  2365             png_bytep dp = row + (png_size_t)row_width - 1;
       
  2366             png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
       
  2367             for (i = 0; i < row_width; i++)
       
  2368             {
       
  2369                *dp = (png_byte)((*sp >> shift) & 0x03);
       
  2370 
       
  2371                if (shift == 6)
       
  2372                {
       
  2373                   shift = 0;
       
  2374                   sp--;
       
  2375                }
       
  2376 
       
  2377                else
       
  2378                   shift += 2;
       
  2379 
       
  2380                dp--;
       
  2381             }
       
  2382             break;
       
  2383          }
       
  2384 
       
  2385          case 4:
       
  2386          {
       
  2387             png_bytep sp = row + (png_size_t)((row_width - 1) >> 1);
       
  2388             png_bytep dp = row + (png_size_t)row_width - 1;
       
  2389             png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
       
  2390             for (i = 0; i < row_width; i++)
       
  2391             {
       
  2392                *dp = (png_byte)((*sp >> shift) & 0x0f);
       
  2393 
       
  2394                if (shift == 4)
       
  2395                {
       
  2396                   shift = 0;
       
  2397                   sp--;
       
  2398                }
       
  2399 
       
  2400                else
       
  2401                   shift = 4;
       
  2402 
       
  2403                dp--;
       
  2404             }
       
  2405             break;
       
  2406          }
       
  2407 
       
  2408          default:
       
  2409             break;
       
  2410       }
       
  2411       row_info->bit_depth = 8;
       
  2412       row_info->pixel_depth = (png_byte)(8 * row_info->channels);
       
  2413       row_info->rowbytes = row_width * row_info->channels;
       
  2414    }
       
  2415 }
       
  2416 #endif
       
  2417 
       
  2418 #ifdef PNG_READ_SHIFT_SUPPORTED
       
  2419 /* Reverse the effects of png_do_shift.  This routine merely shifts the
       
  2420  * pixels back to their significant bits values.  Thus, if you have
       
  2421  * a row of bit depth 8, but only 5 are significant, this will shift
       
  2422  * the values back to 0 through 31.
       
  2423  */
       
  2424 void /* PRIVATE */
       
  2425 png_do_unshift(png_row_infop row_info, png_bytep row,
       
  2426     png_const_color_8p sig_bits)
       
  2427 {
       
  2428    png_debug(1, "in png_do_unshift");
       
  2429 
       
  2430    if (
       
  2431        row_info->color_type != PNG_COLOR_TYPE_PALETTE)
       
  2432    {
       
  2433       int shift[4];
       
  2434       int channels = 0;
       
  2435       int c;
       
  2436       png_uint_16 value = 0;
       
  2437       png_uint_32 row_width = row_info->width;
       
  2438 
       
  2439       if (row_info->color_type & PNG_COLOR_MASK_COLOR)
       
  2440       {
       
  2441          shift[channels++] = row_info->bit_depth - sig_bits->red;
       
  2442          shift[channels++] = row_info->bit_depth - sig_bits->green;
       
  2443          shift[channels++] = row_info->bit_depth - sig_bits->blue;
       
  2444       }
       
  2445 
       
  2446       else
       
  2447       {
       
  2448          shift[channels++] = row_info->bit_depth - sig_bits->gray;
       
  2449       }
       
  2450 
       
  2451       if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
       
  2452       {
       
  2453          shift[channels++] = row_info->bit_depth - sig_bits->alpha;
       
  2454       }
       
  2455 
       
  2456       for (c = 0; c < channels; c++)
       
  2457       {
       
  2458          if (shift[c] <= 0)
       
  2459             shift[c] = 0;
       
  2460 
       
  2461          else
       
  2462             value = 1;
       
  2463       }
       
  2464 
       
  2465       if (!value)
       
  2466          return;
       
  2467 
       
  2468       switch (row_info->bit_depth)
       
  2469       {
       
  2470          default:
       
  2471             break;
       
  2472 
       
  2473          case 2:
       
  2474          {
       
  2475             png_bytep bp;
       
  2476             png_size_t i;
       
  2477             png_size_t istop = row_info->rowbytes;
       
  2478 
       
  2479             for (bp = row, i = 0; i < istop; i++)
       
  2480             {
       
  2481                *bp >>= 1;
       
  2482                *bp++ &= 0x55;
       
  2483             }
       
  2484             break;
       
  2485          }
       
  2486 
       
  2487          case 4:
       
  2488          {
       
  2489             png_bytep bp = row;
       
  2490             png_size_t i;
       
  2491             png_size_t istop = row_info->rowbytes;
       
  2492             png_byte mask = (png_byte)((((int)0xf0 >> shift[0]) & (int)0xf0) |
       
  2493                 (png_byte)((int)0xf >> shift[0]));
       
  2494 
       
  2495             for (i = 0; i < istop; i++)
       
  2496             {
       
  2497                *bp >>= shift[0];
       
  2498                *bp++ &= mask;
       
  2499             }
       
  2500             break;
       
  2501          }
       
  2502 
       
  2503          case 8:
       
  2504          {
       
  2505             png_bytep bp = row;
       
  2506             png_uint_32 i;
       
  2507             png_uint_32 istop = row_width * channels;
       
  2508 
       
  2509             for (i = 0; i < istop; i++)
       
  2510             {
       
  2511                *bp++ >>= shift[i%channels];
       
  2512             }
       
  2513             break;
       
  2514          }
       
  2515 
       
  2516 #ifdef PNG_READ_16BIT_SUPPORTED
       
  2517          case 16:
       
  2518          {
       
  2519             png_bytep bp = row;
       
  2520             png_uint_32 i;
       
  2521             png_uint_32 istop = channels * row_width;
       
  2522 
       
  2523             for (i = 0; i < istop; i++)
       
  2524             {
       
  2525                value = (png_uint_16)((*bp << 8) + *(bp + 1));
       
  2526                value >>= shift[i%channels];
       
  2527                *bp++ = (png_byte)(value >> 8);
       
  2528                *bp++ = (png_byte)(value & 0xff);
       
  2529             }
       
  2530             break;
       
  2531          }
       
  2532 #endif
       
  2533       }
       
  2534    }
       
  2535 }
       
  2536 #endif
       
  2537 
       
  2538 #ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
       
  2539 /* Scale rows of bit depth 16 down to 8 accurately */
       
  2540 void /* PRIVATE */
       
  2541 png_do_scale_16_to_8(png_row_infop row_info, png_bytep row)
       
  2542 {
       
  2543    png_debug(1, "in png_do_scale_16_to_8");
       
  2544 
       
  2545    if (row_info->bit_depth == 16)
       
  2546    {
       
  2547       png_bytep sp = row; /* source */
       
  2548       png_bytep dp = row; /* destinaton */
       
  2549       png_bytep ep = sp + row_info->rowbytes; /* end+1 */
       
  2550 
       
  2551       while (sp < ep)
       
  2552       {
       
  2553          /* The input is an array of 16 bit components, these must be scaled to
       
  2554           * 8 bits each.  For a 16 bit value V the required value (from the PNG
       
  2555           * specification) is:
       
  2556           *
       
  2557           *    (V * 255) / 65535
       
  2558           *
       
  2559           * This reduces to round(V / 257), or floor((V + 128.5)/257)
       
  2560           *
       
  2561           * Represent V as the two byte value vhi.vlo.  Make a guess that the
       
  2562           * result is the top byte of V, vhi, then the correction to this value
       
  2563           * is:
       
  2564           *
       
  2565           *    error = floor(((V-vhi.vhi) + 128.5) / 257)
       
  2566           *          = floor(((vlo-vhi) + 128.5) / 257)
       
  2567           *
       
  2568           * This can be approximated using integer arithmetic (and a signed
       
  2569           * shift):
       
  2570           *
       
  2571           *    error = (vlo-vhi+128) >> 8;
       
  2572           *
       
  2573           * The approximate differs from the exact answer only when (vlo-vhi) is
       
  2574           * 128; it then gives a correction of +1 when the exact correction is
       
  2575           * 0.  This gives 128 errors.  The exact answer (correct for all 16 bit
       
  2576           * input values) is:
       
  2577           *
       
  2578           *    error = (vlo-vhi+128)*65535 >> 24;
       
  2579           *
       
  2580           * An alternative arithmetic calculation which also gives no errors is:
       
  2581           *
       
  2582           *    (V * 255 + 32895) >> 16
       
  2583           */
       
  2584 
       
  2585          png_int_32 tmp = *sp++; /* must be signed! */
       
  2586          tmp += (((int)*sp++ - tmp + 128) * 65535) >> 24;
       
  2587          *dp++ = (png_byte)tmp;
       
  2588       }
       
  2589 
       
  2590       row_info->bit_depth = 8;
       
  2591       row_info->pixel_depth = (png_byte)(8 * row_info->channels);
       
  2592       row_info->rowbytes = row_info->width * row_info->channels;
       
  2593    }
       
  2594 }
       
  2595 #endif
       
  2596 
       
  2597 #ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
       
  2598 void /* PRIVATE */
       
  2599 /* Simply discard the low byte.  This was the default behavior prior
       
  2600  * to libpng-1.5.4.
       
  2601  */
       
  2602 png_do_chop(png_row_infop row_info, png_bytep row)
       
  2603 {
       
  2604    png_debug(1, "in png_do_chop");
       
  2605 
       
  2606    if (row_info->bit_depth == 16)
       
  2607    {
       
  2608       png_bytep sp = row; /* source */
       
  2609       png_bytep dp = row; /* destinaton */
       
  2610       png_bytep ep = sp + row_info->rowbytes; /* end+1 */
       
  2611 
       
  2612       while (sp < ep)
       
  2613       {
       
  2614          *dp++ = *sp;
       
  2615          sp += 2; /* skip low byte */
       
  2616       }
       
  2617 
       
  2618       row_info->bit_depth = 8;
       
  2619       row_info->pixel_depth = (png_byte)(8 * row_info->channels);
       
  2620       row_info->rowbytes = row_info->width * row_info->channels;
       
  2621    }
       
  2622 }
       
  2623 #endif
       
  2624 
       
  2625 #ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
       
  2626 void /* PRIVATE */
       
  2627 png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
       
  2628 {
       
  2629    png_debug(1, "in png_do_read_swap_alpha");
       
  2630 
       
  2631    {
       
  2632       png_uint_32 row_width = row_info->width;
       
  2633       if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
       
  2634       {
       
  2635          /* This converts from RGBA to ARGB */
       
  2636          if (row_info->bit_depth == 8)
       
  2637          {
       
  2638             png_bytep sp = row + row_info->rowbytes;
       
  2639             png_bytep dp = sp;
       
  2640             png_byte save;
       
  2641             png_uint_32 i;
       
  2642 
       
  2643             for (i = 0; i < row_width; i++)
       
  2644             {
       
  2645                save = *(--sp);
       
  2646                *(--dp) = *(--sp);
       
  2647                *(--dp) = *(--sp);
       
  2648                *(--dp) = *(--sp);
       
  2649                *(--dp) = save;
       
  2650             }
       
  2651          }
       
  2652 
       
  2653 #ifdef PNG_READ_16BIT_SUPPORTED
       
  2654          /* This converts from RRGGBBAA to AARRGGBB */
       
  2655          else
       
  2656          {
       
  2657             png_bytep sp = row + row_info->rowbytes;
       
  2658             png_bytep dp = sp;
       
  2659             png_byte save[2];
       
  2660             png_uint_32 i;
       
  2661 
       
  2662             for (i = 0; i < row_width; i++)
       
  2663             {
       
  2664                save[0] = *(--sp);
       
  2665                save[1] = *(--sp);
       
  2666                *(--dp) = *(--sp);
       
  2667                *(--dp) = *(--sp);
       
  2668                *(--dp) = *(--sp);
       
  2669                *(--dp) = *(--sp);
       
  2670                *(--dp) = *(--sp);
       
  2671                *(--dp) = *(--sp);
       
  2672                *(--dp) = save[0];
       
  2673                *(--dp) = save[1];
       
  2674             }
       
  2675          }
       
  2676 #endif
       
  2677       }
       
  2678 
       
  2679       else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
       
  2680       {
       
  2681          /* This converts from GA to AG */
       
  2682          if (row_info->bit_depth == 8)
       
  2683          {
       
  2684             png_bytep sp = row + row_info->rowbytes;
       
  2685             png_bytep dp = sp;
       
  2686             png_byte save;
       
  2687             png_uint_32 i;
       
  2688 
       
  2689             for (i = 0; i < row_width; i++)
       
  2690             {
       
  2691                save = *(--sp);
       
  2692                *(--dp) = *(--sp);
       
  2693                *(--dp) = save;
       
  2694             }
       
  2695          }
       
  2696 
       
  2697 #ifdef PNG_READ_16BIT_SUPPORTED
       
  2698          /* This converts from GGAA to AAGG */
       
  2699          else
       
  2700          {
       
  2701             png_bytep sp = row + row_info->rowbytes;
       
  2702             png_bytep dp = sp;
       
  2703             png_byte save[2];
       
  2704             png_uint_32 i;
       
  2705 
       
  2706             for (i = 0; i < row_width; i++)
       
  2707             {
       
  2708                save[0] = *(--sp);
       
  2709                save[1] = *(--sp);
       
  2710                *(--dp) = *(--sp);
       
  2711                *(--dp) = *(--sp);
       
  2712                *(--dp) = save[0];
       
  2713                *(--dp) = save[1];
       
  2714             }
       
  2715          }
       
  2716 #endif
       
  2717       }
       
  2718    }
       
  2719 }
       
  2720 #endif
       
  2721 
       
  2722 #ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
       
  2723 void /* PRIVATE */
       
  2724 png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
       
  2725 {
       
  2726    png_uint_32 row_width;
       
  2727    png_debug(1, "in png_do_read_invert_alpha");
       
  2728 
       
  2729    row_width = row_info->width;
       
  2730    if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
       
  2731    {
       
  2732       if (row_info->bit_depth == 8)
       
  2733       {
       
  2734          /* This inverts the alpha channel in RGBA */
       
  2735          png_bytep sp = row + row_info->rowbytes;
       
  2736          png_bytep dp = sp;
       
  2737          png_uint_32 i;
       
  2738 
       
  2739          for (i = 0; i < row_width; i++)
       
  2740          {
       
  2741             *(--dp) = (png_byte)(255 - *(--sp));
       
  2742 
       
  2743 /*          This does nothing:
       
  2744             *(--dp) = *(--sp);
       
  2745             *(--dp) = *(--sp);
       
  2746             *(--dp) = *(--sp);
       
  2747             We can replace it with:
       
  2748 */
       
  2749             sp-=3;
       
  2750             dp=sp;
       
  2751          }
       
  2752       }
       
  2753 
       
  2754 #ifdef PNG_READ_16BIT_SUPPORTED
       
  2755       /* This inverts the alpha channel in RRGGBBAA */
       
  2756       else
       
  2757       {
       
  2758          png_bytep sp = row + row_info->rowbytes;
       
  2759          png_bytep dp = sp;
       
  2760          png_uint_32 i;
       
  2761 
       
  2762          for (i = 0; i < row_width; i++)
       
  2763          {
       
  2764             *(--dp) = (png_byte)(255 - *(--sp));
       
  2765             *(--dp) = (png_byte)(255 - *(--sp));
       
  2766 
       
  2767 /*          This does nothing:
       
  2768             *(--dp) = *(--sp);
       
  2769             *(--dp) = *(--sp);
       
  2770             *(--dp) = *(--sp);
       
  2771             *(--dp) = *(--sp);
       
  2772             *(--dp) = *(--sp);
       
  2773             *(--dp) = *(--sp);
       
  2774             We can replace it with:
       
  2775 */
       
  2776             sp-=6;
       
  2777             dp=sp;
       
  2778          }
       
  2779       }
       
  2780 #endif
       
  2781    }
       
  2782    else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
       
  2783    {
       
  2784       if (row_info->bit_depth == 8)
       
  2785       {
       
  2786          /* This inverts the alpha channel in GA */
       
  2787          png_bytep sp = row + row_info->rowbytes;
       
  2788          png_bytep dp = sp;
       
  2789          png_uint_32 i;
       
  2790 
       
  2791          for (i = 0; i < row_width; i++)
       
  2792          {
       
  2793             *(--dp) = (png_byte)(255 - *(--sp));
       
  2794             *(--dp) = *(--sp);
       
  2795          }
       
  2796       }
       
  2797 
       
  2798 #ifdef PNG_READ_16BIT_SUPPORTED
       
  2799       else
       
  2800       {
       
  2801          /* This inverts the alpha channel in GGAA */
       
  2802          png_bytep sp  = row + row_info->rowbytes;
       
  2803          png_bytep dp = sp;
       
  2804          png_uint_32 i;
       
  2805 
       
  2806          for (i = 0; i < row_width; i++)
       
  2807          {
       
  2808             *(--dp) = (png_byte)(255 - *(--sp));
       
  2809             *(--dp) = (png_byte)(255 - *(--sp));
       
  2810 /*
       
  2811             *(--dp) = *(--sp);
       
  2812             *(--dp) = *(--sp);
       
  2813 */
       
  2814             sp-=2;
       
  2815             dp=sp;
       
  2816          }
       
  2817       }
       
  2818 #endif
       
  2819    }
       
  2820 }
       
  2821 #endif
       
  2822 
       
  2823 #ifdef PNG_READ_FILLER_SUPPORTED
       
  2824 /* Add filler channel if we have RGB color */
       
  2825 void /* PRIVATE */
       
  2826 png_do_read_filler(png_row_infop row_info, png_bytep row,
       
  2827     png_uint_32 filler, png_uint_32 flags)
       
  2828 {
       
  2829    png_uint_32 i;
       
  2830    png_uint_32 row_width = row_info->width;
       
  2831 
       
  2832 #ifdef PNG_READ_16BIT_SUPPORTED
       
  2833    png_byte hi_filler = (png_byte)((filler>>8) & 0xff);
       
  2834 #endif
       
  2835    png_byte lo_filler = (png_byte)(filler & 0xff);
       
  2836 
       
  2837    png_debug(1, "in png_do_read_filler");
       
  2838 
       
  2839    if (
       
  2840        row_info->color_type == PNG_COLOR_TYPE_GRAY)
       
  2841    {
       
  2842       if (row_info->bit_depth == 8)
       
  2843       {
       
  2844          if (flags & PNG_FLAG_FILLER_AFTER)
       
  2845          {
       
  2846             /* This changes the data from G to GX */
       
  2847             png_bytep sp = row + (png_size_t)row_width;
       
  2848             png_bytep dp =  sp + (png_size_t)row_width;
       
  2849             for (i = 1; i < row_width; i++)
       
  2850             {
       
  2851                *(--dp) = lo_filler;
       
  2852                *(--dp) = *(--sp);
       
  2853             }
       
  2854             *(--dp) = lo_filler;
       
  2855             row_info->channels = 2;
       
  2856             row_info->pixel_depth = 16;
       
  2857             row_info->rowbytes = row_width * 2;
       
  2858          }
       
  2859 
       
  2860          else
       
  2861          {
       
  2862             /* This changes the data from G to XG */
       
  2863             png_bytep sp = row + (png_size_t)row_width;
       
  2864             png_bytep dp = sp  + (png_size_t)row_width;
       
  2865             for (i = 0; i < row_width; i++)
       
  2866             {
       
  2867                *(--dp) = *(--sp);
       
  2868                *(--dp) = lo_filler;
       
  2869             }
       
  2870             row_info->channels = 2;
       
  2871             row_info->pixel_depth = 16;
       
  2872             row_info->rowbytes = row_width * 2;
       
  2873          }
       
  2874       }
       
  2875 
       
  2876 #ifdef PNG_READ_16BIT_SUPPORTED
       
  2877       else if (row_info->bit_depth == 16)
       
  2878       {
       
  2879          if (flags & PNG_FLAG_FILLER_AFTER)
       
  2880          {
       
  2881             /* This changes the data from GG to GGXX */
       
  2882             png_bytep sp = row + (png_size_t)row_width * 2;
       
  2883             png_bytep dp = sp  + (png_size_t)row_width * 2;
       
  2884             for (i = 1; i < row_width; i++)
       
  2885             {
       
  2886                *(--dp) = hi_filler;
       
  2887                *(--dp) = lo_filler;
       
  2888                *(--dp) = *(--sp);
       
  2889                *(--dp) = *(--sp);
       
  2890             }
       
  2891             *(--dp) = hi_filler;
       
  2892             *(--dp) = lo_filler;
       
  2893             row_info->channels = 2;
       
  2894             row_info->pixel_depth = 32;
       
  2895             row_info->rowbytes = row_width * 4;
       
  2896          }
       
  2897 
       
  2898          else
       
  2899          {
       
  2900             /* This changes the data from GG to XXGG */
       
  2901             png_bytep sp = row + (png_size_t)row_width * 2;
       
  2902             png_bytep dp = sp  + (png_size_t)row_width * 2;
       
  2903             for (i = 0; i < row_width; i++)
       
  2904             {
       
  2905                *(--dp) = *(--sp);
       
  2906                *(--dp) = *(--sp);
       
  2907                *(--dp) = hi_filler;
       
  2908                *(--dp) = lo_filler;
       
  2909             }
       
  2910             row_info->channels = 2;
       
  2911             row_info->pixel_depth = 32;
       
  2912             row_info->rowbytes = row_width * 4;
       
  2913          }
       
  2914       }
       
  2915 #endif
       
  2916    } /* COLOR_TYPE == GRAY */
       
  2917    else if (row_info->color_type == PNG_COLOR_TYPE_RGB)
       
  2918    {
       
  2919       if (row_info->bit_depth == 8)
       
  2920       {
       
  2921          if (flags & PNG_FLAG_FILLER_AFTER)
       
  2922          {
       
  2923             /* This changes the data from RGB to RGBX */
       
  2924             png_bytep sp = row + (png_size_t)row_width * 3;
       
  2925             png_bytep dp = sp  + (png_size_t)row_width;
       
  2926             for (i = 1; i < row_width; i++)
       
  2927             {
       
  2928                *(--dp) = lo_filler;
       
  2929                *(--dp) = *(--sp);
       
  2930                *(--dp) = *(--sp);
       
  2931                *(--dp) = *(--sp);
       
  2932             }
       
  2933             *(--dp) = lo_filler;
       
  2934             row_info->channels = 4;
       
  2935             row_info->pixel_depth = 32;
       
  2936             row_info->rowbytes = row_width * 4;
       
  2937          }
       
  2938 
       
  2939          else
       
  2940          {
       
  2941             /* This changes the data from RGB to XRGB */
       
  2942             png_bytep sp = row + (png_size_t)row_width * 3;
       
  2943             png_bytep dp = sp + (png_size_t)row_width;
       
  2944             for (i = 0; i < row_width; i++)
       
  2945             {
       
  2946                *(--dp) = *(--sp);
       
  2947                *(--dp) = *(--sp);
       
  2948                *(--dp) = *(--sp);
       
  2949                *(--dp) = lo_filler;
       
  2950             }
       
  2951             row_info->channels = 4;
       
  2952             row_info->pixel_depth = 32;
       
  2953             row_info->rowbytes = row_width * 4;
       
  2954          }
       
  2955       }
       
  2956 
       
  2957 #ifdef PNG_READ_16BIT_SUPPORTED
       
  2958       else if (row_info->bit_depth == 16)
       
  2959       {
       
  2960          if (flags & PNG_FLAG_FILLER_AFTER)
       
  2961          {
       
  2962             /* This changes the data from RRGGBB to RRGGBBXX */
       
  2963             png_bytep sp = row + (png_size_t)row_width * 6;
       
  2964             png_bytep dp = sp  + (png_size_t)row_width * 2;
       
  2965             for (i = 1; i < row_width; i++)
       
  2966             {
       
  2967                *(--dp) = hi_filler;
       
  2968                *(--dp) = lo_filler;
       
  2969                *(--dp) = *(--sp);
       
  2970                *(--dp) = *(--sp);
       
  2971                *(--dp) = *(--sp);
       
  2972                *(--dp) = *(--sp);
       
  2973                *(--dp) = *(--sp);
       
  2974                *(--dp) = *(--sp);
       
  2975             }
       
  2976             *(--dp) = hi_filler;
       
  2977             *(--dp) = lo_filler;
       
  2978             row_info->channels = 4;
       
  2979             row_info->pixel_depth = 64;
       
  2980             row_info->rowbytes = row_width * 8;
       
  2981          }
       
  2982 
       
  2983          else
       
  2984          {
       
  2985             /* This changes the data from RRGGBB to XXRRGGBB */
       
  2986             png_bytep sp = row + (png_size_t)row_width * 6;
       
  2987             png_bytep dp = sp  + (png_size_t)row_width * 2;
       
  2988             for (i = 0; i < row_width; i++)
       
  2989             {
       
  2990                *(--dp) = *(--sp);
       
  2991                *(--dp) = *(--sp);
       
  2992                *(--dp) = *(--sp);
       
  2993                *(--dp) = *(--sp);
       
  2994                *(--dp) = *(--sp);
       
  2995                *(--dp) = *(--sp);
       
  2996                *(--dp) = hi_filler;
       
  2997                *(--dp) = lo_filler;
       
  2998             }
       
  2999 
       
  3000             row_info->channels = 4;
       
  3001             row_info->pixel_depth = 64;
       
  3002             row_info->rowbytes = row_width * 8;
       
  3003          }
       
  3004       }
       
  3005 #endif
       
  3006    } /* COLOR_TYPE == RGB */
       
  3007 }
       
  3008 #endif
       
  3009 
       
  3010 #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
       
  3011 /* Expand grayscale files to RGB, with or without alpha */
       
  3012 void /* PRIVATE */
       
  3013 png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
       
  3014 {
       
  3015    png_uint_32 i;
       
  3016    png_uint_32 row_width = row_info->width;
       
  3017 
       
  3018    png_debug(1, "in png_do_gray_to_rgb");
       
  3019 
       
  3020    if (row_info->bit_depth >= 8 &&
       
  3021        !(row_info->color_type & PNG_COLOR_MASK_COLOR))
       
  3022    {
       
  3023       if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
       
  3024       {
       
  3025          if (row_info->bit_depth == 8)
       
  3026          {
       
  3027             /* This changes G to RGB */
       
  3028             png_bytep sp = row + (png_size_t)row_width - 1;
       
  3029             png_bytep dp = sp  + (png_size_t)row_width * 2;
       
  3030             for (i = 0; i < row_width; i++)
       
  3031             {
       
  3032                *(dp--) = *sp;
       
  3033                *(dp--) = *sp;
       
  3034                *(dp--) = *(sp--);
       
  3035             }
       
  3036          }
       
  3037 
       
  3038          else
       
  3039          {
       
  3040             /* This changes GG to RRGGBB */
       
  3041             png_bytep sp = row + (png_size_t)row_width * 2 - 1;
       
  3042             png_bytep dp = sp  + (png_size_t)row_width * 4;
       
  3043             for (i = 0; i < row_width; i++)
       
  3044             {
       
  3045                *(dp--) = *sp;
       
  3046                *(dp--) = *(sp - 1);
       
  3047                *(dp--) = *sp;
       
  3048                *(dp--) = *(sp - 1);
       
  3049                *(dp--) = *(sp--);
       
  3050                *(dp--) = *(sp--);
       
  3051             }
       
  3052          }
       
  3053       }
       
  3054 
       
  3055       else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
       
  3056       {
       
  3057          if (row_info->bit_depth == 8)
       
  3058          {
       
  3059             /* This changes GA to RGBA */
       
  3060             png_bytep sp = row + (png_size_t)row_width * 2 - 1;
       
  3061             png_bytep dp = sp  + (png_size_t)row_width * 2;
       
  3062             for (i = 0; i < row_width; i++)
       
  3063             {
       
  3064                *(dp--) = *(sp--);
       
  3065                *(dp--) = *sp;
       
  3066                *(dp--) = *sp;
       
  3067                *(dp--) = *(sp--);
       
  3068             }
       
  3069          }
       
  3070 
       
  3071          else
       
  3072          {
       
  3073             /* This changes GGAA to RRGGBBAA */
       
  3074             png_bytep sp = row + (png_size_t)row_width * 4 - 1;
       
  3075             png_bytep dp = sp  + (png_size_t)row_width * 4;
       
  3076             for (i = 0; i < row_width; i++)
       
  3077             {
       
  3078                *(dp--) = *(sp--);
       
  3079                *(dp--) = *(sp--);
       
  3080                *(dp--) = *sp;
       
  3081                *(dp--) = *(sp - 1);
       
  3082                *(dp--) = *sp;
       
  3083                *(dp--) = *(sp - 1);
       
  3084                *(dp--) = *(sp--);
       
  3085                *(dp--) = *(sp--);
       
  3086             }
       
  3087          }
       
  3088       }
       
  3089       row_info->channels += (png_byte)2;
       
  3090       row_info->color_type |= PNG_COLOR_MASK_COLOR;
       
  3091       row_info->pixel_depth = (png_byte)(row_info->channels *
       
  3092           row_info->bit_depth);
       
  3093       row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
       
  3094    }
       
  3095 }
       
  3096 #endif
       
  3097 
       
  3098 #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
       
  3099 /* Reduce RGB files to grayscale, with or without alpha
       
  3100  * using the equation given in Poynton's ColorFAQ at
       
  3101  * <http://www.inforamp.net/~poynton/>  (THIS LINK IS DEAD June 2008)
       
  3102  * New link:
       
  3103  * <http://www.poynton.com/notes/colour_and_gamma/>
       
  3104  * Charles Poynton poynton at poynton.com
       
  3105  *
       
  3106  *     Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
       
  3107  *
       
  3108  *  We approximate this with
       
  3109  *
       
  3110  *     Y = 0.21268 * R    + 0.7151 * G    + 0.07217 * B
       
  3111  *
       
  3112  *  which can be expressed with integers as
       
  3113  *
       
  3114  *     Y = (6969 * R + 23434 * G + 2365 * B)/32768
       
  3115  *
       
  3116  *  The calculation is to be done in a linear colorspace.
       
  3117  *
       
  3118  *  Other integer coefficents can be used via png_set_rgb_to_gray().
       
  3119  */
       
  3120 int /* PRIVATE */
       
  3121 png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
       
  3122 
       
  3123 {
       
  3124    png_uint_32 i;
       
  3125 
       
  3126    png_uint_32 row_width = row_info->width;
       
  3127    int rgb_error = 0;
       
  3128 
       
  3129    png_debug(1, "in png_do_rgb_to_gray");
       
  3130 
       
  3131    if (!(row_info->color_type & PNG_COLOR_MASK_PALETTE) &&
       
  3132        (row_info->color_type & PNG_COLOR_MASK_COLOR))
       
  3133    {
       
  3134       png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff;
       
  3135       png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff;
       
  3136       png_uint_32 bc = png_ptr->rgb_to_gray_blue_coeff;
       
  3137 
       
  3138       if (row_info->color_type == PNG_COLOR_TYPE_RGB)
       
  3139       {
       
  3140          if (row_info->bit_depth == 8)
       
  3141          {
       
  3142 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
       
  3143             if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
       
  3144             {
       
  3145                png_bytep sp = row;
       
  3146                png_bytep dp = row;
       
  3147 
       
  3148                for (i = 0; i < row_width; i++)
       
  3149                {
       
  3150                   png_byte red   = png_ptr->gamma_to_1[*(sp++)];
       
  3151                   png_byte green = png_ptr->gamma_to_1[*(sp++)];
       
  3152                   png_byte blue  = png_ptr->gamma_to_1[*(sp++)];
       
  3153 
       
  3154                   if (red != green || red != blue)
       
  3155                   {
       
  3156                      rgb_error |= 1;
       
  3157                      *(dp++) = png_ptr->gamma_from_1[
       
  3158                          (rc*red + gc*green + bc*blue)>>15];
       
  3159                   }
       
  3160 
       
  3161                   else
       
  3162                      *(dp++) = *(sp - 1);
       
  3163                }
       
  3164             }
       
  3165             else
       
  3166 #endif
       
  3167             {
       
  3168                png_bytep sp = row;
       
  3169                png_bytep dp = row;
       
  3170                for (i = 0; i < row_width; i++)
       
  3171                {
       
  3172                   png_byte red   = *(sp++);
       
  3173                   png_byte green = *(sp++);
       
  3174                   png_byte blue  = *(sp++);
       
  3175 
       
  3176                   if (red != green || red != blue)
       
  3177                   {
       
  3178                      rgb_error |= 1;
       
  3179                      *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15);
       
  3180                   }
       
  3181 
       
  3182                   else
       
  3183                      *(dp++) = *(sp - 1);
       
  3184                }
       
  3185             }
       
  3186          }
       
  3187 
       
  3188          else /* RGB bit_depth == 16 */
       
  3189          {
       
  3190 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
       
  3191             if (png_ptr->gamma_16_to_1 != NULL &&
       
  3192                 png_ptr->gamma_16_from_1 != NULL)
       
  3193             {
       
  3194                png_bytep sp = row;
       
  3195                png_bytep dp = row;
       
  3196                for (i = 0; i < row_width; i++)
       
  3197                {
       
  3198                   png_uint_16 red, green, blue, w;
       
  3199 
       
  3200                   red   = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
       
  3201                   green = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
       
  3202                   blue  = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
       
  3203 
       
  3204                   if (red == green && red == blue)
       
  3205                      w = red;
       
  3206 
       
  3207                   else
       
  3208                   {
       
  3209                      png_uint_16 red_1   = png_ptr->gamma_16_to_1[(red&0xff)
       
  3210                          >> png_ptr->gamma_shift][red>>8];
       
  3211                      png_uint_16 green_1 =
       
  3212                          png_ptr->gamma_16_to_1[(green&0xff) >>
       
  3213                          png_ptr->gamma_shift][green>>8];
       
  3214                      png_uint_16 blue_1  = png_ptr->gamma_16_to_1[(blue&0xff)
       
  3215                          >> png_ptr->gamma_shift][blue>>8];
       
  3216                      png_uint_16 gray16  = (png_uint_16)((rc*red_1 + gc*green_1
       
  3217                          + bc*blue_1)>>15);
       
  3218                      w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
       
  3219                          png_ptr->gamma_shift][gray16 >> 8];
       
  3220                      rgb_error |= 1;
       
  3221                   }
       
  3222 
       
  3223                   *(dp++) = (png_byte)((w>>8) & 0xff);
       
  3224                   *(dp++) = (png_byte)(w & 0xff);
       
  3225                }
       
  3226             }
       
  3227             else
       
  3228 #endif
       
  3229             {
       
  3230                png_bytep sp = row;
       
  3231                png_bytep dp = row;
       
  3232                for (i = 0; i < row_width; i++)
       
  3233                {
       
  3234                   png_uint_16 red, green, blue, gray16;
       
  3235 
       
  3236                   red   = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
       
  3237                   green = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
       
  3238                   blue  = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
       
  3239 
       
  3240                   if (red != green || red != blue)
       
  3241                      rgb_error |= 1;
       
  3242 
       
  3243                   gray16  = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
       
  3244                   *(dp++) = (png_byte)((gray16>>8) & 0xff);
       
  3245                   *(dp++) = (png_byte)(gray16 & 0xff);
       
  3246                }
       
  3247             }
       
  3248          }
       
  3249       }
       
  3250       if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
       
  3251       {
       
  3252          if (row_info->bit_depth == 8)
       
  3253          {
       
  3254 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
       
  3255             if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
       
  3256             {
       
  3257                png_bytep sp = row;
       
  3258                png_bytep dp = row;
       
  3259                for (i = 0; i < row_width; i++)
       
  3260                {
       
  3261                   png_byte red   = png_ptr->gamma_to_1[*(sp++)];
       
  3262                   png_byte green = png_ptr->gamma_to_1[*(sp++)];
       
  3263                   png_byte blue  = png_ptr->gamma_to_1[*(sp++)];
       
  3264 
       
  3265                   if (red != green || red != blue)
       
  3266                      rgb_error |= 1;
       
  3267 
       
  3268                   *(dp++) =  png_ptr->gamma_from_1
       
  3269                       [(rc*red + gc*green + bc*blue)>>15];
       
  3270 
       
  3271                   *(dp++) = *(sp++);  /* alpha */
       
  3272                }
       
  3273             }
       
  3274             else
       
  3275 #endif
       
  3276             {
       
  3277                png_bytep sp = row;
       
  3278                png_bytep dp = row;
       
  3279                for (i = 0; i < row_width; i++)
       
  3280                {
       
  3281                   png_byte red   = *(sp++);
       
  3282                   png_byte green = *(sp++);
       
  3283                   png_byte blue  = *(sp++);
       
  3284                   if (red != green || red != blue)
       
  3285                      rgb_error |= 1;
       
  3286 
       
  3287                   *(dp++) =  (png_byte)((rc*red + gc*green + bc*blue)>>15);
       
  3288                   *(dp++) = *(sp++);  /* alpha */
       
  3289                }
       
  3290             }
       
  3291          }
       
  3292          else /* RGBA bit_depth == 16 */
       
  3293          {
       
  3294 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
       
  3295             if (png_ptr->gamma_16_to_1 != NULL &&
       
  3296                 png_ptr->gamma_16_from_1 != NULL)
       
  3297             {
       
  3298                png_bytep sp = row;
       
  3299                png_bytep dp = row;
       
  3300                for (i = 0; i < row_width; i++)
       
  3301                {
       
  3302                   png_uint_16 red, green, blue, w;
       
  3303 
       
  3304                   red   = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
       
  3305                   green = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
       
  3306                   blue  = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
       
  3307 
       
  3308                   if (red == green && red == blue)
       
  3309                      w = red;
       
  3310 
       
  3311                   else
       
  3312                   {
       
  3313                      png_uint_16 red_1   = png_ptr->gamma_16_to_1[(red&0xff) >>
       
  3314                          png_ptr->gamma_shift][red>>8];
       
  3315 
       
  3316                      png_uint_16 green_1 =
       
  3317                          png_ptr->gamma_16_to_1[(green&0xff) >>
       
  3318                          png_ptr->gamma_shift][green>>8];
       
  3319 
       
  3320                      png_uint_16 blue_1  = png_ptr->gamma_16_to_1[(blue&0xff) >>
       
  3321                          png_ptr->gamma_shift][blue>>8];
       
  3322 
       
  3323                      png_uint_16 gray16  = (png_uint_16)((rc * red_1
       
  3324                          + gc * green_1 + bc * blue_1)>>15);
       
  3325 
       
  3326                      w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
       
  3327                          png_ptr->gamma_shift][gray16 >> 8];
       
  3328 
       
  3329                      rgb_error |= 1;
       
  3330                   }
       
  3331 
       
  3332                   *(dp++) = (png_byte)((w>>8) & 0xff);
       
  3333                   *(dp++) = (png_byte)(w & 0xff);
       
  3334                   *(dp++) = *(sp++);  /* alpha */
       
  3335                   *(dp++) = *(sp++);
       
  3336                }
       
  3337             }
       
  3338             else
       
  3339 #endif
       
  3340             {
       
  3341                png_bytep sp = row;
       
  3342                png_bytep dp = row;
       
  3343                for (i = 0; i < row_width; i++)
       
  3344                {
       
  3345                   png_uint_16 red, green, blue, gray16;
       
  3346                   red   = (png_uint_16)((*(sp)<<8) | *(sp + 1)); sp += 2;
       
  3347                   green = (png_uint_16)((*(sp)<<8) | *(sp + 1)); sp += 2;
       
  3348                   blue  = (png_uint_16)((*(sp)<<8) | *(sp + 1)); sp += 2;
       
  3349 
       
  3350                   if (red != green || red != blue)
       
  3351                      rgb_error |= 1;
       
  3352 
       
  3353                   gray16  = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
       
  3354                   *(dp++) = (png_byte)((gray16>>8) & 0xff);
       
  3355                   *(dp++) = (png_byte)(gray16 & 0xff);
       
  3356                   *(dp++) = *(sp++);  /* alpha */
       
  3357                   *(dp++) = *(sp++);
       
  3358                }
       
  3359             }
       
  3360          }
       
  3361       }
       
  3362       row_info->channels -= 2;
       
  3363       row_info->color_type = (png_byte)(row_info->color_type &
       
  3364           ~PNG_COLOR_MASK_COLOR);
       
  3365       row_info->pixel_depth = (png_byte)(row_info->channels *
       
  3366           row_info->bit_depth);
       
  3367       row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
       
  3368    }
       
  3369    return rgb_error;
       
  3370 }
       
  3371 #endif
       
  3372 #endif /* PNG_READ_TRANSFORMS_SUPPORTED */
       
  3373 
       
  3374 #ifdef PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED
       
  3375 /* Build a grayscale palette.  Palette is assumed to be 1 << bit_depth
       
  3376  * large of png_color.  This lets grayscale images be treated as
       
  3377  * paletted.  Most useful for gamma correction and simplification
       
  3378  * of code.  This API is not used internally.
       
  3379  */
       
  3380 void PNGAPI
       
  3381 png_build_grayscale_palette(int bit_depth, png_colorp palette)
       
  3382 {
       
  3383    int num_palette;
       
  3384    int color_inc;
       
  3385    int i;
       
  3386    int v;
       
  3387 
       
  3388    png_debug(1, "in png_do_build_grayscale_palette");
       
  3389 
       
  3390    if (palette == NULL)
       
  3391       return;
       
  3392 
       
  3393    switch (bit_depth)
       
  3394    {
       
  3395       case 1:
       
  3396          num_palette = 2;
       
  3397          color_inc = 0xff;
       
  3398          break;
       
  3399 
       
  3400       case 2:
       
  3401          num_palette = 4;
       
  3402          color_inc = 0x55;
       
  3403          break;
       
  3404 
       
  3405       case 4:
       
  3406          num_palette = 16;
       
  3407          color_inc = 0x11;
       
  3408          break;
       
  3409 
       
  3410       case 8:
       
  3411          num_palette = 256;
       
  3412          color_inc = 1;
       
  3413          break;
       
  3414 
       
  3415       default:
       
  3416          num_palette = 0;
       
  3417          color_inc = 0;
       
  3418          break;
       
  3419    }
       
  3420 
       
  3421    for (i = 0, v = 0; i < num_palette; i++, v += color_inc)
       
  3422    {
       
  3423       palette[i].red = (png_byte)v;
       
  3424       palette[i].green = (png_byte)v;
       
  3425       palette[i].blue = (png_byte)v;
       
  3426    }
       
  3427 }
       
  3428 #endif
       
  3429 
       
  3430 
       
  3431 #ifdef PNG_READ_TRANSFORMS_SUPPORTED
       
  3432 #ifdef PNG_READ_BACKGROUND_SUPPORTED
       
  3433 /* Replace any alpha or transparency with the supplied background color.
       
  3434  * "background" is already in the screen gamma, while "background_1" is
       
  3435  * at a gamma of 1.0.  Paletted files have already been taken care of.
       
  3436  */
       
  3437 void /* PRIVATE */
       
  3438 png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
       
  3439 {
       
  3440 #ifdef PNG_READ_GAMMA_SUPPORTED
       
  3441    png_const_bytep gamma_table = png_ptr->gamma_table;
       
  3442    png_const_bytep gamma_from_1 = png_ptr->gamma_from_1;
       
  3443    png_const_bytep gamma_to_1 = png_ptr->gamma_to_1;
       
  3444    png_const_uint_16pp gamma_16 = png_ptr->gamma_16_table;
       
  3445    png_const_uint_16pp gamma_16_from_1 = png_ptr->gamma_16_from_1;
       
  3446    png_const_uint_16pp gamma_16_to_1 = png_ptr->gamma_16_to_1;
       
  3447    int gamma_shift = png_ptr->gamma_shift;
       
  3448 #endif
       
  3449 
       
  3450    png_bytep sp;
       
  3451    png_uint_32 i;
       
  3452    png_uint_32 row_width = row_info->width;
       
  3453    int optimize = (png_ptr->flags & PNG_FLAG_OPTIMIZE_ALPHA) != 0;
       
  3454    int shift;
       
  3455 
       
  3456    png_debug(1, "in png_do_compose");
       
  3457 
       
  3458    {
       
  3459       switch (row_info->color_type)
       
  3460       {
       
  3461          case PNG_COLOR_TYPE_GRAY:
       
  3462          {
       
  3463             switch (row_info->bit_depth)
       
  3464             {
       
  3465                case 1:
       
  3466                {
       
  3467                   sp = row;
       
  3468                   shift = 7;
       
  3469                   for (i = 0; i < row_width; i++)
       
  3470                   {
       
  3471                      if ((png_uint_16)((*sp >> shift) & 0x01)
       
  3472                         == png_ptr->trans_color.gray)
       
  3473                      {
       
  3474                         *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
       
  3475                         *sp |= (png_byte)(png_ptr->background.gray << shift);
       
  3476                      }
       
  3477 
       
  3478                      if (!shift)
       
  3479                      {
       
  3480                         shift = 7;
       
  3481                         sp++;
       
  3482                      }
       
  3483 
       
  3484                      else
       
  3485                         shift--;
       
  3486                   }
       
  3487                   break;
       
  3488                }
       
  3489 
       
  3490                case 2:
       
  3491                {
       
  3492 #ifdef PNG_READ_GAMMA_SUPPORTED
       
  3493                   if (gamma_table != NULL)
       
  3494                   {
       
  3495                      sp = row;
       
  3496                      shift = 6;
       
  3497                      for (i = 0; i < row_width; i++)
       
  3498                      {
       
  3499                         if ((png_uint_16)((*sp >> shift) & 0x03)
       
  3500                             == png_ptr->trans_color.gray)
       
  3501                         {
       
  3502                            *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
       
  3503                            *sp |= (png_byte)(png_ptr->background.gray << shift);
       
  3504                         }
       
  3505 
       
  3506                         else
       
  3507                         {
       
  3508                            png_byte p = (png_byte)((*sp >> shift) & 0x03);
       
  3509                            png_byte g = (png_byte)((gamma_table [p | (p << 2) |
       
  3510                                (p << 4) | (p << 6)] >> 6) & 0x03);
       
  3511                            *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
       
  3512                            *sp |= (png_byte)(g << shift);
       
  3513                         }
       
  3514 
       
  3515                         if (!shift)
       
  3516                         {
       
  3517                            shift = 6;
       
  3518                            sp++;
       
  3519                         }
       
  3520 
       
  3521                         else
       
  3522                            shift -= 2;
       
  3523                      }
       
  3524                   }
       
  3525 
       
  3526                   else
       
  3527 #endif
       
  3528                   {
       
  3529                      sp = row;
       
  3530                      shift = 6;
       
  3531                      for (i = 0; i < row_width; i++)
       
  3532                      {
       
  3533                         if ((png_uint_16)((*sp >> shift) & 0x03)
       
  3534                             == png_ptr->trans_color.gray)
       
  3535                         {
       
  3536                            *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
       
  3537                            *sp |= (png_byte)(png_ptr->background.gray << shift);
       
  3538                         }
       
  3539 
       
  3540                         if (!shift)
       
  3541                         {
       
  3542                            shift = 6;
       
  3543                            sp++;
       
  3544                         }
       
  3545 
       
  3546                         else
       
  3547                            shift -= 2;
       
  3548                      }
       
  3549                   }
       
  3550                   break;
       
  3551                }
       
  3552 
       
  3553                case 4:
       
  3554                {
       
  3555 #ifdef PNG_READ_GAMMA_SUPPORTED
       
  3556                   if (gamma_table != NULL)
       
  3557                   {
       
  3558                      sp = row;
       
  3559                      shift = 4;
       
  3560                      for (i = 0; i < row_width; i++)
       
  3561                      {
       
  3562                         if ((png_uint_16)((*sp >> shift) & 0x0f)
       
  3563                             == png_ptr->trans_color.gray)
       
  3564                         {
       
  3565                            *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
       
  3566                            *sp |= (png_byte)(png_ptr->background.gray << shift);
       
  3567                         }
       
  3568 
       
  3569                         else
       
  3570                         {
       
  3571                            png_byte p = (png_byte)((*sp >> shift) & 0x0f);
       
  3572                            png_byte g = (png_byte)((gamma_table[p |
       
  3573                                (p << 4)] >> 4) & 0x0f);
       
  3574                            *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
       
  3575                            *sp |= (png_byte)(g << shift);
       
  3576                         }
       
  3577 
       
  3578                         if (!shift)
       
  3579                         {
       
  3580                            shift = 4;
       
  3581                            sp++;
       
  3582                         }
       
  3583 
       
  3584                         else
       
  3585                            shift -= 4;
       
  3586                      }
       
  3587                   }
       
  3588 
       
  3589                   else
       
  3590 #endif
       
  3591                   {
       
  3592                      sp = row;
       
  3593                      shift = 4;
       
  3594                      for (i = 0; i < row_width; i++)
       
  3595                      {
       
  3596                         if ((png_uint_16)((*sp >> shift) & 0x0f)
       
  3597                             == png_ptr->trans_color.gray)
       
  3598                         {
       
  3599                            *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
       
  3600                            *sp |= (png_byte)(png_ptr->background.gray << shift);
       
  3601                         }
       
  3602 
       
  3603                         if (!shift)
       
  3604                         {
       
  3605                            shift = 4;
       
  3606                            sp++;
       
  3607                         }
       
  3608 
       
  3609                         else
       
  3610                            shift -= 4;
       
  3611                      }
       
  3612                   }
       
  3613                   break;
       
  3614                }
       
  3615 
       
  3616                case 8:
       
  3617                {
       
  3618 #ifdef PNG_READ_GAMMA_SUPPORTED
       
  3619                   if (gamma_table != NULL)
       
  3620                   {
       
  3621                      sp = row;
       
  3622                      for (i = 0; i < row_width; i++, sp++)
       
  3623                      {
       
  3624                         if (*sp == png_ptr->trans_color.gray)
       
  3625                            *sp = (png_byte)png_ptr->background.gray;
       
  3626 
       
  3627                         else
       
  3628                            *sp = gamma_table[*sp];
       
  3629                      }
       
  3630                   }
       
  3631                   else
       
  3632 #endif
       
  3633                   {
       
  3634                      sp = row;
       
  3635                      for (i = 0; i < row_width; i++, sp++)
       
  3636                      {
       
  3637                         if (*sp == png_ptr->trans_color.gray)
       
  3638                            *sp = (png_byte)png_ptr->background.gray;
       
  3639                      }
       
  3640                   }
       
  3641                   break;
       
  3642                }
       
  3643 
       
  3644                case 16:
       
  3645                {
       
  3646 #ifdef PNG_READ_GAMMA_SUPPORTED
       
  3647                   if (gamma_16 != NULL)
       
  3648                   {
       
  3649                      sp = row;
       
  3650                      for (i = 0; i < row_width; i++, sp += 2)
       
  3651                      {
       
  3652                         png_uint_16 v;
       
  3653 
       
  3654                         v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
       
  3655 
       
  3656                         if (v == png_ptr->trans_color.gray)
       
  3657                         {
       
  3658                            /* Background is already in screen gamma */
       
  3659                            *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
       
  3660                            *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
       
  3661                         }
       
  3662 
       
  3663                         else
       
  3664                         {
       
  3665                            v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
       
  3666                            *sp = (png_byte)((v >> 8) & 0xff);
       
  3667                            *(sp + 1) = (png_byte)(v & 0xff);
       
  3668                         }
       
  3669                      }
       
  3670                   }
       
  3671                   else
       
  3672 #endif
       
  3673                   {
       
  3674                      sp = row;
       
  3675                      for (i = 0; i < row_width; i++, sp += 2)
       
  3676                      {
       
  3677                         png_uint_16 v;
       
  3678 
       
  3679                         v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
       
  3680 
       
  3681                         if (v == png_ptr->trans_color.gray)
       
  3682                         {
       
  3683                            *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
       
  3684                            *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
       
  3685                         }
       
  3686                      }
       
  3687                   }
       
  3688                   break;
       
  3689                }
       
  3690 
       
  3691                default:
       
  3692                   break;
       
  3693             }
       
  3694             break;
       
  3695          }
       
  3696 
       
  3697          case PNG_COLOR_TYPE_RGB:
       
  3698          {
       
  3699             if (row_info->bit_depth == 8)
       
  3700             {
       
  3701 #ifdef PNG_READ_GAMMA_SUPPORTED
       
  3702                if (gamma_table != NULL)
       
  3703                {
       
  3704                   sp = row;
       
  3705                   for (i = 0; i < row_width; i++, sp += 3)
       
  3706                   {
       
  3707                      if (*sp == png_ptr->trans_color.red &&
       
  3708                          *(sp + 1) == png_ptr->trans_color.green &&
       
  3709                          *(sp + 2) == png_ptr->trans_color.blue)
       
  3710                      {
       
  3711                         *sp = (png_byte)png_ptr->background.red;
       
  3712                         *(sp + 1) = (png_byte)png_ptr->background.green;
       
  3713                         *(sp + 2) = (png_byte)png_ptr->background.blue;
       
  3714                      }
       
  3715 
       
  3716                      else
       
  3717                      {
       
  3718                         *sp = gamma_table[*sp];
       
  3719                         *(sp + 1) = gamma_table[*(sp + 1)];
       
  3720                         *(sp + 2) = gamma_table[*(sp + 2)];
       
  3721                      }
       
  3722                   }
       
  3723                }
       
  3724                else
       
  3725 #endif
       
  3726                {
       
  3727                   sp = row;
       
  3728                   for (i = 0; i < row_width; i++, sp += 3)
       
  3729                   {
       
  3730                      if (*sp == png_ptr->trans_color.red &&
       
  3731                          *(sp + 1) == png_ptr->trans_color.green &&
       
  3732                          *(sp + 2) == png_ptr->trans_color.blue)
       
  3733                      {
       
  3734                         *sp = (png_byte)png_ptr->background.red;
       
  3735                         *(sp + 1) = (png_byte)png_ptr->background.green;
       
  3736                         *(sp + 2) = (png_byte)png_ptr->background.blue;
       
  3737                      }
       
  3738                   }
       
  3739                }
       
  3740             }
       
  3741             else /* if (row_info->bit_depth == 16) */
       
  3742             {
       
  3743 #ifdef PNG_READ_GAMMA_SUPPORTED
       
  3744                if (gamma_16 != NULL)
       
  3745                {
       
  3746                   sp = row;
       
  3747                   for (i = 0; i < row_width; i++, sp += 6)
       
  3748                   {
       
  3749                      png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
       
  3750 
       
  3751                      png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
       
  3752                          + *(sp + 3));
       
  3753 
       
  3754                      png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
       
  3755                          + *(sp + 5));
       
  3756 
       
  3757                      if (r == png_ptr->trans_color.red &&
       
  3758                          g == png_ptr->trans_color.green &&
       
  3759                          b == png_ptr->trans_color.blue)
       
  3760                      {
       
  3761                         /* Background is already in screen gamma */
       
  3762                         *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
       
  3763                         *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
       
  3764                         *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff);
       
  3765                         *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff);
       
  3766                         *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff);
       
  3767                         *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
       
  3768                      }
       
  3769 
       
  3770                      else
       
  3771                      {
       
  3772                         png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
       
  3773                         *sp = (png_byte)((v >> 8) & 0xff);
       
  3774                         *(sp + 1) = (png_byte)(v & 0xff);
       
  3775 
       
  3776                         v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
       
  3777                         *(sp + 2) = (png_byte)((v >> 8) & 0xff);
       
  3778                         *(sp + 3) = (png_byte)(v & 0xff);
       
  3779 
       
  3780                         v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
       
  3781                         *(sp + 4) = (png_byte)((v >> 8) & 0xff);
       
  3782                         *(sp + 5) = (png_byte)(v & 0xff);
       
  3783                      }
       
  3784                   }
       
  3785                }
       
  3786 
       
  3787                else
       
  3788 #endif
       
  3789                {
       
  3790                   sp = row;
       
  3791                   for (i = 0; i < row_width; i++, sp += 6)
       
  3792                   {
       
  3793                      png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
       
  3794 
       
  3795                      png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
       
  3796                          + *(sp + 3));
       
  3797 
       
  3798                      png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
       
  3799                          + *(sp + 5));
       
  3800 
       
  3801                      if (r == png_ptr->trans_color.red &&
       
  3802                          g == png_ptr->trans_color.green &&
       
  3803                          b == png_ptr->trans_color.blue)
       
  3804                      {
       
  3805                         *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
       
  3806                         *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
       
  3807                         *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff);
       
  3808                         *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff);
       
  3809                         *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff);
       
  3810                         *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
       
  3811                      }
       
  3812                   }
       
  3813                }
       
  3814             }
       
  3815             break;
       
  3816          }
       
  3817 
       
  3818          case PNG_COLOR_TYPE_GRAY_ALPHA:
       
  3819          {
       
  3820             if (row_info->bit_depth == 8)
       
  3821             {
       
  3822 #ifdef PNG_READ_GAMMA_SUPPORTED
       
  3823                if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
       
  3824                    gamma_table != NULL)
       
  3825                {
       
  3826                   sp = row;
       
  3827                   for (i = 0; i < row_width; i++, sp += 2)
       
  3828                   {
       
  3829                      png_uint_16 a = *(sp + 1);
       
  3830 
       
  3831                      if (a == 0xff)
       
  3832                         *sp = gamma_table[*sp];
       
  3833 
       
  3834                      else if (a == 0)
       
  3835                      {
       
  3836                         /* Background is already in screen gamma */
       
  3837                         *sp = (png_byte)png_ptr->background.gray;
       
  3838                      }
       
  3839 
       
  3840                      else
       
  3841                      {
       
  3842                         png_byte v, w;
       
  3843 
       
  3844                         v = gamma_to_1[*sp];
       
  3845                         png_composite(w, v, a, png_ptr->background_1.gray);
       
  3846                         if (!optimize)
       
  3847                            w = gamma_from_1[w];
       
  3848                         *sp = w;
       
  3849                      }
       
  3850                   }
       
  3851                }
       
  3852                else
       
  3853 #endif
       
  3854                {
       
  3855                   sp = row;
       
  3856                   for (i = 0; i < row_width; i++, sp += 2)
       
  3857                   {
       
  3858                      png_byte a = *(sp + 1);
       
  3859 
       
  3860                      if (a == 0)
       
  3861                         *sp = (png_byte)png_ptr->background.gray;
       
  3862 
       
  3863                      else if (a < 0xff)
       
  3864                         png_composite(*sp, *sp, a, png_ptr->background_1.gray);
       
  3865                   }
       
  3866                }
       
  3867             }
       
  3868             else /* if (png_ptr->bit_depth == 16) */
       
  3869             {
       
  3870 #ifdef PNG_READ_GAMMA_SUPPORTED
       
  3871                if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
       
  3872                    gamma_16_to_1 != NULL)
       
  3873                {
       
  3874                   sp = row;
       
  3875                   for (i = 0; i < row_width; i++, sp += 4)
       
  3876                   {
       
  3877                      png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8)
       
  3878                          + *(sp + 3));
       
  3879 
       
  3880                      if (a == (png_uint_16)0xffff)
       
  3881                      {
       
  3882                         png_uint_16 v;
       
  3883 
       
  3884                         v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
       
  3885                         *sp = (png_byte)((v >> 8) & 0xff);
       
  3886                         *(sp + 1) = (png_byte)(v & 0xff);
       
  3887                      }
       
  3888 
       
  3889                      else if (a == 0)
       
  3890                      {
       
  3891                         /* Background is already in screen gamma */
       
  3892                         *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
       
  3893                         *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
       
  3894                      }
       
  3895 
       
  3896                      else
       
  3897                      {
       
  3898                         png_uint_16 g, v, w;
       
  3899 
       
  3900                         g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
       
  3901                         png_composite_16(v, g, a, png_ptr->background_1.gray);
       
  3902                         if (optimize)
       
  3903                            w = v;
       
  3904                         else
       
  3905                            w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8];
       
  3906                         *sp = (png_byte)((w >> 8) & 0xff);
       
  3907                         *(sp + 1) = (png_byte)(w & 0xff);
       
  3908                      }
       
  3909                   }
       
  3910                }
       
  3911                else
       
  3912 #endif
       
  3913                {
       
  3914                   sp = row;
       
  3915                   for (i = 0; i < row_width; i++, sp += 4)
       
  3916                   {
       
  3917                      png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8)
       
  3918                          + *(sp + 3));
       
  3919 
       
  3920                      if (a == 0)
       
  3921                      {
       
  3922                         *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
       
  3923                         *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
       
  3924                      }
       
  3925 
       
  3926                      else if (a < 0xffff)
       
  3927                      {
       
  3928                         png_uint_16 g, v;
       
  3929 
       
  3930                         g = (png_uint_16)(((*sp) << 8) + *(sp + 1));
       
  3931                         png_composite_16(v, g, a, png_ptr->background_1.gray);
       
  3932                         *sp = (png_byte)((v >> 8) & 0xff);
       
  3933                         *(sp + 1) = (png_byte)(v & 0xff);
       
  3934                      }
       
  3935                   }
       
  3936                }
       
  3937             }
       
  3938             break;
       
  3939          }
       
  3940 
       
  3941          case PNG_COLOR_TYPE_RGB_ALPHA:
       
  3942          {
       
  3943             if (row_info->bit_depth == 8)
       
  3944             {
       
  3945 #ifdef PNG_READ_GAMMA_SUPPORTED
       
  3946                if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
       
  3947                    gamma_table != NULL)
       
  3948                {
       
  3949                   sp = row;
       
  3950                   for (i = 0; i < row_width; i++, sp += 4)
       
  3951                   {
       
  3952                      png_byte a = *(sp + 3);
       
  3953 
       
  3954                      if (a == 0xff)
       
  3955                      {
       
  3956                         *sp = gamma_table[*sp];
       
  3957                         *(sp + 1) = gamma_table[*(sp + 1)];
       
  3958                         *(sp + 2) = gamma_table[*(sp + 2)];
       
  3959                      }
       
  3960 
       
  3961                      else if (a == 0)
       
  3962                      {
       
  3963                         /* Background is already in screen gamma */
       
  3964                         *sp = (png_byte)png_ptr->background.red;
       
  3965                         *(sp + 1) = (png_byte)png_ptr->background.green;
       
  3966                         *(sp + 2) = (png_byte)png_ptr->background.blue;
       
  3967                      }
       
  3968 
       
  3969                      else
       
  3970                      {
       
  3971                         png_byte v, w;
       
  3972 
       
  3973                         v = gamma_to_1[*sp];
       
  3974                         png_composite(w, v, a, png_ptr->background_1.red);
       
  3975                         if (!optimize) w = gamma_from_1[w];
       
  3976                         *sp = w;
       
  3977 
       
  3978                         v = gamma_to_1[*(sp + 1)];
       
  3979                         png_composite(w, v, a, png_ptr->background_1.green);
       
  3980                         if (!optimize) w = gamma_from_1[w];
       
  3981                         *(sp + 1) = w;
       
  3982 
       
  3983                         v = gamma_to_1[*(sp + 2)];
       
  3984                         png_composite(w, v, a, png_ptr->background_1.blue);
       
  3985                         if (!optimize) w = gamma_from_1[w];
       
  3986                         *(sp + 2) = w;
       
  3987                      }
       
  3988                   }
       
  3989                }
       
  3990                else
       
  3991 #endif
       
  3992                {
       
  3993                   sp = row;
       
  3994                   for (i = 0; i < row_width; i++, sp += 4)
       
  3995                   {
       
  3996                      png_byte a = *(sp + 3);
       
  3997 
       
  3998                      if (a == 0)
       
  3999                      {
       
  4000                         *sp = (png_byte)png_ptr->background.red;
       
  4001                         *(sp + 1) = (png_byte)png_ptr->background.green;
       
  4002                         *(sp + 2) = (png_byte)png_ptr->background.blue;
       
  4003                      }
       
  4004 
       
  4005                      else if (a < 0xff)
       
  4006                      {
       
  4007                         png_composite(*sp, *sp, a, png_ptr->background.red);
       
  4008 
       
  4009                         png_composite(*(sp + 1), *(sp + 1), a,
       
  4010                             png_ptr->background.green);
       
  4011 
       
  4012                         png_composite(*(sp + 2), *(sp + 2), a,
       
  4013                             png_ptr->background.blue);
       
  4014                      }
       
  4015                   }
       
  4016                }
       
  4017             }
       
  4018             else /* if (row_info->bit_depth == 16) */
       
  4019             {
       
  4020 #ifdef PNG_READ_GAMMA_SUPPORTED
       
  4021                if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
       
  4022                    gamma_16_to_1 != NULL)
       
  4023                {
       
  4024                   sp = row;
       
  4025                   for (i = 0; i < row_width; i++, sp += 8)
       
  4026                   {
       
  4027                      png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
       
  4028                          << 8) + (png_uint_16)(*(sp + 7)));
       
  4029 
       
  4030                      if (a == (png_uint_16)0xffff)
       
  4031                      {
       
  4032                         png_uint_16 v;
       
  4033 
       
  4034                         v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
       
  4035                         *sp = (png_byte)((v >> 8) & 0xff);
       
  4036                         *(sp + 1) = (png_byte)(v & 0xff);
       
  4037 
       
  4038                         v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
       
  4039                         *(sp + 2) = (png_byte)((v >> 8) & 0xff);
       
  4040                         *(sp + 3) = (png_byte)(v & 0xff);
       
  4041 
       
  4042                         v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
       
  4043                         *(sp + 4) = (png_byte)((v >> 8) & 0xff);
       
  4044                         *(sp + 5) = (png_byte)(v & 0xff);
       
  4045                      }
       
  4046 
       
  4047                      else if (a == 0)
       
  4048                      {
       
  4049                         /* Background is already in screen gamma */
       
  4050                         *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
       
  4051                         *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
       
  4052                         *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff);
       
  4053                         *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff);
       
  4054                         *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff);
       
  4055                         *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
       
  4056                      }
       
  4057 
       
  4058                      else
       
  4059                      {
       
  4060                         png_uint_16 v, w;
       
  4061 
       
  4062                         v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
       
  4063                         png_composite_16(w, v, a, png_ptr->background_1.red);
       
  4064                         if (!optimize)
       
  4065                            w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
       
  4066                         *sp = (png_byte)((w >> 8) & 0xff);
       
  4067                         *(sp + 1) = (png_byte)(w & 0xff);
       
  4068 
       
  4069                         v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)];
       
  4070                         png_composite_16(w, v, a, png_ptr->background_1.green);
       
  4071                         if (!optimize)
       
  4072                            w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
       
  4073 
       
  4074                         *(sp + 2) = (png_byte)((w >> 8) & 0xff);
       
  4075                         *(sp + 3) = (png_byte)(w & 0xff);
       
  4076 
       
  4077                         v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)];
       
  4078                         png_composite_16(w, v, a, png_ptr->background_1.blue);
       
  4079                         if (!optimize)
       
  4080                            w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
       
  4081 
       
  4082                         *(sp + 4) = (png_byte)((w >> 8) & 0xff);
       
  4083                         *(sp + 5) = (png_byte)(w & 0xff);
       
  4084                      }
       
  4085                   }
       
  4086                }
       
  4087 
       
  4088                else
       
  4089 #endif
       
  4090                {
       
  4091                   sp = row;
       
  4092                   for (i = 0; i < row_width; i++, sp += 8)
       
  4093                   {
       
  4094                      png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
       
  4095                          << 8) + (png_uint_16)(*(sp + 7)));
       
  4096 
       
  4097                      if (a == 0)
       
  4098                      {
       
  4099                         *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
       
  4100                         *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
       
  4101                         *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff);
       
  4102                         *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff);
       
  4103                         *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff);
       
  4104                         *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
       
  4105                      }
       
  4106 
       
  4107                      else if (a < 0xffff)
       
  4108                      {
       
  4109                         png_uint_16 v;
       
  4110 
       
  4111                         png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
       
  4112                         png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
       
  4113                             + *(sp + 3));
       
  4114                         png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
       
  4115                             + *(sp + 5));
       
  4116 
       
  4117                         png_composite_16(v, r, a, png_ptr->background.red);
       
  4118                         *sp = (png_byte)((v >> 8) & 0xff);
       
  4119                         *(sp + 1) = (png_byte)(v & 0xff);
       
  4120 
       
  4121                         png_composite_16(v, g, a, png_ptr->background.green);
       
  4122                         *(sp + 2) = (png_byte)((v >> 8) & 0xff);
       
  4123                         *(sp + 3) = (png_byte)(v & 0xff);
       
  4124 
       
  4125                         png_composite_16(v, b, a, png_ptr->background.blue);
       
  4126                         *(sp + 4) = (png_byte)((v >> 8) & 0xff);
       
  4127                         *(sp + 5) = (png_byte)(v & 0xff);
       
  4128                      }
       
  4129                   }
       
  4130                }
       
  4131             }
       
  4132             break;
       
  4133          }
       
  4134 
       
  4135          default:
       
  4136             break;
       
  4137       }
       
  4138    }
       
  4139 }
       
  4140 #endif
       
  4141 
       
  4142 #ifdef PNG_READ_GAMMA_SUPPORTED
       
  4143 /* Gamma correct the image, avoiding the alpha channel.  Make sure
       
  4144  * you do this after you deal with the transparency issue on grayscale
       
  4145  * or RGB images. If your bit depth is 8, use gamma_table, if it
       
  4146  * is 16, use gamma_16_table and gamma_shift.  Build these with
       
  4147  * build_gamma_table().
       
  4148  */
       
  4149 void /* PRIVATE */
       
  4150 png_do_gamma(png_row_infop row_info, png_bytep row, png_structp png_ptr)
       
  4151 {
       
  4152    png_const_bytep gamma_table = png_ptr->gamma_table;
       
  4153    png_const_uint_16pp gamma_16_table = png_ptr->gamma_16_table;
       
  4154    int gamma_shift = png_ptr->gamma_shift;
       
  4155 
       
  4156    png_bytep sp;
       
  4157    png_uint_32 i;
       
  4158    png_uint_32 row_width=row_info->width;
       
  4159 
       
  4160    png_debug(1, "in png_do_gamma");
       
  4161 
       
  4162    if (((row_info->bit_depth <= 8 && gamma_table != NULL) ||
       
  4163        (row_info->bit_depth == 16 && gamma_16_table != NULL)))
       
  4164    {
       
  4165       switch (row_info->color_type)
       
  4166       {
       
  4167          case PNG_COLOR_TYPE_RGB:
       
  4168          {
       
  4169             if (row_info->bit_depth == 8)
       
  4170             {
       
  4171                sp = row;
       
  4172                for (i = 0; i < row_width; i++)
       
  4173                {
       
  4174                   *sp = gamma_table[*sp];
       
  4175                   sp++;
       
  4176                   *sp = gamma_table[*sp];
       
  4177                   sp++;
       
  4178                   *sp = gamma_table[*sp];
       
  4179                   sp++;
       
  4180                }
       
  4181             }
       
  4182 
       
  4183             else /* if (row_info->bit_depth == 16) */
       
  4184             {
       
  4185                sp = row;
       
  4186                for (i = 0; i < row_width; i++)
       
  4187                {
       
  4188                   png_uint_16 v;
       
  4189 
       
  4190                   v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
       
  4191                   *sp = (png_byte)((v >> 8) & 0xff);
       
  4192                   *(sp + 1) = (png_byte)(v & 0xff);
       
  4193                   sp += 2;
       
  4194 
       
  4195                   v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
       
  4196                   *sp = (png_byte)((v >> 8) & 0xff);
       
  4197                   *(sp + 1) = (png_byte)(v & 0xff);
       
  4198                   sp += 2;
       
  4199 
       
  4200                   v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
       
  4201                   *sp = (png_byte)((v >> 8) & 0xff);
       
  4202                   *(sp + 1) = (png_byte)(v & 0xff);
       
  4203                   sp += 2;
       
  4204                }
       
  4205             }
       
  4206             break;
       
  4207          }
       
  4208 
       
  4209          case PNG_COLOR_TYPE_RGB_ALPHA:
       
  4210          {
       
  4211             if (row_info->bit_depth == 8)
       
  4212             {
       
  4213                sp = row;
       
  4214                for (i = 0; i < row_width; i++)
       
  4215                {
       
  4216                   *sp = gamma_table[*sp];
       
  4217                   sp++;
       
  4218 
       
  4219                   *sp = gamma_table[*sp];
       
  4220                   sp++;
       
  4221 
       
  4222                   *sp = gamma_table[*sp];
       
  4223                   sp++;
       
  4224 
       
  4225                   sp++;
       
  4226                }
       
  4227             }
       
  4228 
       
  4229             else /* if (row_info->bit_depth == 16) */
       
  4230             {
       
  4231                sp = row;
       
  4232                for (i = 0; i < row_width; i++)
       
  4233                {
       
  4234                   png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
       
  4235                   *sp = (png_byte)((v >> 8) & 0xff);
       
  4236                   *(sp + 1) = (png_byte)(v & 0xff);
       
  4237                   sp += 2;
       
  4238 
       
  4239                   v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
       
  4240                   *sp = (png_byte)((v >> 8) & 0xff);
       
  4241                   *(sp + 1) = (png_byte)(v & 0xff);
       
  4242                   sp += 2;
       
  4243 
       
  4244                   v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
       
  4245                   *sp = (png_byte)((v >> 8) & 0xff);
       
  4246                   *(sp + 1) = (png_byte)(v & 0xff);
       
  4247                   sp += 4;
       
  4248                }
       
  4249             }
       
  4250             break;
       
  4251          }
       
  4252 
       
  4253          case PNG_COLOR_TYPE_GRAY_ALPHA:
       
  4254          {
       
  4255             if (row_info->bit_depth == 8)
       
  4256             {
       
  4257                sp = row;
       
  4258                for (i = 0; i < row_width; i++)
       
  4259                {
       
  4260                   *sp = gamma_table[*sp];
       
  4261                   sp += 2;
       
  4262                }
       
  4263             }
       
  4264 
       
  4265             else /* if (row_info->bit_depth == 16) */
       
  4266             {
       
  4267                sp = row;
       
  4268                for (i = 0; i < row_width; i++)
       
  4269                {
       
  4270                   png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
       
  4271                   *sp = (png_byte)((v >> 8) & 0xff);
       
  4272                   *(sp + 1) = (png_byte)(v & 0xff);
       
  4273                   sp += 4;
       
  4274                }
       
  4275             }
       
  4276             break;
       
  4277          }
       
  4278 
       
  4279          case PNG_COLOR_TYPE_GRAY:
       
  4280          {
       
  4281             if (row_info->bit_depth == 2)
       
  4282             {
       
  4283                sp = row;
       
  4284                for (i = 0; i < row_width; i += 4)
       
  4285                {
       
  4286                   int a = *sp & 0xc0;
       
  4287                   int b = *sp & 0x30;
       
  4288                   int c = *sp & 0x0c;
       
  4289                   int d = *sp & 0x03;
       
  4290 
       
  4291                   *sp = (png_byte)(
       
  4292                       ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)])   ) & 0xc0)|
       
  4293                       ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)|
       
  4294                       ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)|
       
  4295                       ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) ));
       
  4296                   sp++;
       
  4297                }
       
  4298             }
       
  4299 
       
  4300             if (row_info->bit_depth == 4)
       
  4301             {
       
  4302                sp = row;
       
  4303                for (i = 0; i < row_width; i += 2)
       
  4304                {
       
  4305                   int msb = *sp & 0xf0;
       
  4306                   int lsb = *sp & 0x0f;
       
  4307 
       
  4308                   *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0)
       
  4309                       | (((int)gamma_table[(lsb << 4) | lsb]) >> 4));
       
  4310                   sp++;
       
  4311                }
       
  4312             }
       
  4313 
       
  4314             else if (row_info->bit_depth == 8)
       
  4315             {
       
  4316                sp = row;
       
  4317                for (i = 0; i < row_width; i++)
       
  4318                {
       
  4319                   *sp = gamma_table[*sp];
       
  4320                   sp++;
       
  4321                }
       
  4322             }
       
  4323 
       
  4324             else if (row_info->bit_depth == 16)
       
  4325             {
       
  4326                sp = row;
       
  4327                for (i = 0; i < row_width; i++)
       
  4328                {
       
  4329                   png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
       
  4330                   *sp = (png_byte)((v >> 8) & 0xff);
       
  4331                   *(sp + 1) = (png_byte)(v & 0xff);
       
  4332                   sp += 2;
       
  4333                }
       
  4334             }
       
  4335             break;
       
  4336          }
       
  4337 
       
  4338          default:
       
  4339             break;
       
  4340       }
       
  4341    }
       
  4342 }
       
  4343 #endif
       
  4344 
       
  4345 #ifdef PNG_READ_ALPHA_MODE_SUPPORTED
       
  4346 /* Encode the alpha channel to the output gamma (the input channel is always
       
  4347  * linear.)  Called only with color types that have an alpha channel.  Needs the
       
  4348  * from_1 tables.
       
  4349  */
       
  4350 void /* PRIVATE */
       
  4351 png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structp png_ptr)
       
  4352 {
       
  4353    png_uint_32 row_width = row_info->width;
       
  4354 
       
  4355    png_debug(1, "in png_do_encode_alpha");
       
  4356 
       
  4357    if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
       
  4358    {
       
  4359       if (row_info->bit_depth == 8)
       
  4360       {
       
  4361          PNG_CONST png_bytep table = png_ptr->gamma_from_1;
       
  4362 
       
  4363          if (table != NULL)
       
  4364          {
       
  4365             PNG_CONST int step =
       
  4366                (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 4 : 2;
       
  4367 
       
  4368             /* The alpha channel is the last component: */
       
  4369             row += step - 1;
       
  4370 
       
  4371             for (; row_width > 0; --row_width, row += step)
       
  4372                *row = table[*row];
       
  4373 
       
  4374             return;
       
  4375          }
       
  4376       }
       
  4377 
       
  4378       else if (row_info->bit_depth == 16)
       
  4379       {
       
  4380          PNG_CONST png_uint_16pp table = png_ptr->gamma_16_from_1;
       
  4381          PNG_CONST int gamma_shift = png_ptr->gamma_shift;
       
  4382 
       
  4383          if (table != NULL)
       
  4384          {
       
  4385             PNG_CONST int step =
       
  4386                (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 8 : 4;
       
  4387 
       
  4388             /* The alpha channel is the last component: */
       
  4389             row += step - 2;
       
  4390 
       
  4391             for (; row_width > 0; --row_width, row += step)
       
  4392             {
       
  4393                png_uint_16 v;
       
  4394 
       
  4395                v = table[*(row + 1) >> gamma_shift][*row];
       
  4396                *row = (png_byte)((v >> 8) & 0xff);
       
  4397                *(row + 1) = (png_byte)(v & 0xff);
       
  4398             }
       
  4399 
       
  4400             return;
       
  4401          }
       
  4402       }
       
  4403    }
       
  4404 
       
  4405    /* Only get to here if called with a weird row_info; no harm has been done,
       
  4406     * so just issue a warning.
       
  4407     */
       
  4408    png_warning(png_ptr, "png_do_encode_alpha: unexpected call");
       
  4409 }
       
  4410 #endif
       
  4411 
       
  4412 #ifdef PNG_READ_EXPAND_SUPPORTED
       
  4413 /* Expands a palette row to an RGB or RGBA row depending
       
  4414  * upon whether you supply trans and num_trans.
       
  4415  */
       
  4416 void /* PRIVATE */
       
  4417 png_do_expand_palette(png_row_infop row_info, png_bytep row,
       
  4418    png_const_colorp palette, png_const_bytep trans_alpha, int num_trans)
       
  4419 {
       
  4420    int shift, value;
       
  4421    png_bytep sp, dp;
       
  4422    png_uint_32 i;
       
  4423    png_uint_32 row_width=row_info->width;
       
  4424 
       
  4425    png_debug(1, "in png_do_expand_palette");
       
  4426 
       
  4427    if (row_info->color_type == PNG_COLOR_TYPE_PALETTE)
       
  4428    {
       
  4429       if (row_info->bit_depth < 8)
       
  4430       {
       
  4431          switch (row_info->bit_depth)
       
  4432          {
       
  4433             case 1:
       
  4434             {
       
  4435                sp = row + (png_size_t)((row_width - 1) >> 3);
       
  4436                dp = row + (png_size_t)row_width - 1;
       
  4437                shift = 7 - (int)((row_width + 7) & 0x07);
       
  4438                for (i = 0; i < row_width; i++)
       
  4439                {
       
  4440                   if ((*sp >> shift) & 0x01)
       
  4441                      *dp = 1;
       
  4442 
       
  4443                   else
       
  4444                      *dp = 0;
       
  4445 
       
  4446                   if (shift == 7)
       
  4447                   {
       
  4448                      shift = 0;
       
  4449                      sp--;
       
  4450                   }
       
  4451 
       
  4452                   else
       
  4453                      shift++;
       
  4454 
       
  4455                   dp--;
       
  4456                }
       
  4457                break;
       
  4458             }
       
  4459 
       
  4460             case 2:
       
  4461             {
       
  4462                sp = row + (png_size_t)((row_width - 1) >> 2);
       
  4463                dp = row + (png_size_t)row_width - 1;
       
  4464                shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
       
  4465                for (i = 0; i < row_width; i++)
       
  4466                {
       
  4467                   value = (*sp >> shift) & 0x03;
       
  4468                   *dp = (png_byte)value;
       
  4469                   if (shift == 6)
       
  4470                   {
       
  4471                      shift = 0;
       
  4472                      sp--;
       
  4473                   }
       
  4474 
       
  4475                   else
       
  4476                      shift += 2;
       
  4477 
       
  4478                   dp--;
       
  4479                }
       
  4480                break;
       
  4481             }
       
  4482 
       
  4483             case 4:
       
  4484             {
       
  4485                sp = row + (png_size_t)((row_width - 1) >> 1);
       
  4486                dp = row + (png_size_t)row_width - 1;
       
  4487                shift = (int)((row_width & 0x01) << 2);
       
  4488                for (i = 0; i < row_width; i++)
       
  4489                {
       
  4490                   value = (*sp >> shift) & 0x0f;
       
  4491                   *dp = (png_byte)value;
       
  4492                   if (shift == 4)
       
  4493                   {
       
  4494                      shift = 0;
       
  4495                      sp--;
       
  4496                   }
       
  4497 
       
  4498                   else
       
  4499                      shift += 4;
       
  4500 
       
  4501                   dp--;
       
  4502                }
       
  4503                break;
       
  4504             }
       
  4505 
       
  4506             default:
       
  4507                break;
       
  4508          }
       
  4509          row_info->bit_depth = 8;
       
  4510          row_info->pixel_depth = 8;
       
  4511          row_info->rowbytes = row_width;
       
  4512       }
       
  4513 
       
  4514       if (row_info->bit_depth == 8)
       
  4515       {
       
  4516          {
       
  4517             if (num_trans > 0)
       
  4518             {
       
  4519                sp = row + (png_size_t)row_width - 1;
       
  4520                dp = row + (png_size_t)(row_width << 2) - 1;
       
  4521 
       
  4522                for (i = 0; i < row_width; i++)
       
  4523                {
       
  4524                   if ((int)(*sp) >= num_trans)
       
  4525                      *dp-- = 0xff;
       
  4526 
       
  4527                   else
       
  4528                      *dp-- = trans_alpha[*sp];
       
  4529 
       
  4530                   *dp-- = palette[*sp].blue;
       
  4531                   *dp-- = palette[*sp].green;
       
  4532                   *dp-- = palette[*sp].red;
       
  4533                   sp--;
       
  4534                }
       
  4535                row_info->bit_depth = 8;
       
  4536                row_info->pixel_depth = 32;
       
  4537                row_info->rowbytes = row_width * 4;
       
  4538                row_info->color_type = 6;
       
  4539                row_info->channels = 4;
       
  4540             }
       
  4541 
       
  4542             else
       
  4543             {
       
  4544                sp = row + (png_size_t)row_width - 1;
       
  4545                dp = row + (png_size_t)(row_width * 3) - 1;
       
  4546 
       
  4547                for (i = 0; i < row_width; i++)
       
  4548                {
       
  4549                   *dp-- = palette[*sp].blue;
       
  4550                   *dp-- = palette[*sp].green;
       
  4551                   *dp-- = palette[*sp].red;
       
  4552                   sp--;
       
  4553                }
       
  4554 
       
  4555                row_info->bit_depth = 8;
       
  4556                row_info->pixel_depth = 24;
       
  4557                row_info->rowbytes = row_width * 3;
       
  4558                row_info->color_type = 2;
       
  4559                row_info->channels = 3;
       
  4560             }
       
  4561          }
       
  4562       }
       
  4563    }
       
  4564 }
       
  4565 
       
  4566 /* If the bit depth < 8, it is expanded to 8.  Also, if the already
       
  4567  * expanded transparency value is supplied, an alpha channel is built.
       
  4568  */
       
  4569 void /* PRIVATE */
       
  4570 png_do_expand(png_row_infop row_info, png_bytep row,
       
  4571     png_const_color_16p trans_color)
       
  4572 {
       
  4573    int shift, value;
       
  4574    png_bytep sp, dp;
       
  4575    png_uint_32 i;
       
  4576    png_uint_32 row_width=row_info->width;
       
  4577 
       
  4578    png_debug(1, "in png_do_expand");
       
  4579 
       
  4580    {
       
  4581       if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
       
  4582       {
       
  4583          png_uint_16 gray = (png_uint_16)(trans_color ? trans_color->gray : 0);
       
  4584 
       
  4585          if (row_info->bit_depth < 8)
       
  4586          {
       
  4587             switch (row_info->bit_depth)
       
  4588             {
       
  4589                case 1:
       
  4590                {
       
  4591                   gray = (png_uint_16)((gray & 0x01) * 0xff);
       
  4592                   sp = row + (png_size_t)((row_width - 1) >> 3);
       
  4593                   dp = row + (png_size_t)row_width - 1;
       
  4594                   shift = 7 - (int)((row_width + 7) & 0x07);
       
  4595                   for (i = 0; i < row_width; i++)
       
  4596                   {
       
  4597                      if ((*sp >> shift) & 0x01)
       
  4598                         *dp = 0xff;
       
  4599 
       
  4600                      else
       
  4601                         *dp = 0;
       
  4602 
       
  4603                      if (shift == 7)
       
  4604                      {
       
  4605                         shift = 0;
       
  4606                         sp--;
       
  4607                      }
       
  4608 
       
  4609                      else
       
  4610                         shift++;
       
  4611 
       
  4612                      dp--;
       
  4613                   }
       
  4614                   break;
       
  4615                }
       
  4616 
       
  4617                case 2:
       
  4618                {
       
  4619                   gray = (png_uint_16)((gray & 0x03) * 0x55);
       
  4620                   sp = row + (png_size_t)((row_width - 1) >> 2);
       
  4621                   dp = row + (png_size_t)row_width - 1;
       
  4622                   shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
       
  4623                   for (i = 0; i < row_width; i++)
       
  4624                   {
       
  4625                      value = (*sp >> shift) & 0x03;
       
  4626                      *dp = (png_byte)(value | (value << 2) | (value << 4) |
       
  4627                         (value << 6));
       
  4628                      if (shift == 6)
       
  4629                      {
       
  4630                         shift = 0;
       
  4631                         sp--;
       
  4632                      }
       
  4633 
       
  4634                      else
       
  4635                         shift += 2;
       
  4636 
       
  4637                      dp--;
       
  4638                   }
       
  4639                   break;
       
  4640                }
       
  4641 
       
  4642                case 4:
       
  4643                {
       
  4644                   gray = (png_uint_16)((gray & 0x0f) * 0x11);
       
  4645                   sp = row + (png_size_t)((row_width - 1) >> 1);
       
  4646                   dp = row + (png_size_t)row_width - 1;
       
  4647                   shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
       
  4648                   for (i = 0; i < row_width; i++)
       
  4649                   {
       
  4650                      value = (*sp >> shift) & 0x0f;
       
  4651                      *dp = (png_byte)(value | (value << 4));
       
  4652                      if (shift == 4)
       
  4653                      {
       
  4654                         shift = 0;
       
  4655                         sp--;
       
  4656                      }
       
  4657 
       
  4658                      else
       
  4659                         shift = 4;
       
  4660 
       
  4661                      dp--;
       
  4662                   }
       
  4663                   break;
       
  4664                }
       
  4665 
       
  4666                default:
       
  4667                   break;
       
  4668             }
       
  4669 
       
  4670             row_info->bit_depth = 8;
       
  4671             row_info->pixel_depth = 8;
       
  4672             row_info->rowbytes = row_width;
       
  4673          }
       
  4674 
       
  4675          if (trans_color != NULL)
       
  4676          {
       
  4677             if (row_info->bit_depth == 8)
       
  4678             {
       
  4679                gray = gray & 0xff;
       
  4680                sp = row + (png_size_t)row_width - 1;
       
  4681                dp = row + (png_size_t)(row_width << 1) - 1;
       
  4682 
       
  4683                for (i = 0; i < row_width; i++)
       
  4684                {
       
  4685                   if (*sp == gray)
       
  4686                      *dp-- = 0;
       
  4687 
       
  4688                   else
       
  4689                      *dp-- = 0xff;
       
  4690 
       
  4691                   *dp-- = *sp--;
       
  4692                }
       
  4693             }
       
  4694 
       
  4695             else if (row_info->bit_depth == 16)
       
  4696             {
       
  4697                png_byte gray_high = (png_byte)((gray >> 8) & 0xff);
       
  4698                png_byte gray_low = (png_byte)(gray & 0xff);
       
  4699                sp = row + row_info->rowbytes - 1;
       
  4700                dp = row + (row_info->rowbytes << 1) - 1;
       
  4701                for (i = 0; i < row_width; i++)
       
  4702                {
       
  4703                   if (*(sp - 1) == gray_high && *(sp) == gray_low)
       
  4704                   {
       
  4705                      *dp-- = 0;
       
  4706                      *dp-- = 0;
       
  4707                   }
       
  4708 
       
  4709                   else
       
  4710                   {
       
  4711                      *dp-- = 0xff;
       
  4712                      *dp-- = 0xff;
       
  4713                   }
       
  4714 
       
  4715                   *dp-- = *sp--;
       
  4716                   *dp-- = *sp--;
       
  4717                }
       
  4718             }
       
  4719 
       
  4720             row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
       
  4721             row_info->channels = 2;
       
  4722             row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1);
       
  4723             row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
       
  4724                row_width);
       
  4725          }
       
  4726       }
       
  4727       else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_color)
       
  4728       {
       
  4729          if (row_info->bit_depth == 8)
       
  4730          {
       
  4731             png_byte red = (png_byte)(trans_color->red & 0xff);
       
  4732             png_byte green = (png_byte)(trans_color->green & 0xff);
       
  4733             png_byte blue = (png_byte)(trans_color->blue & 0xff);
       
  4734             sp = row + (png_size_t)row_info->rowbytes - 1;
       
  4735             dp = row + (png_size_t)(row_width << 2) - 1;
       
  4736             for (i = 0; i < row_width; i++)
       
  4737             {
       
  4738                if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue)
       
  4739                   *dp-- = 0;
       
  4740 
       
  4741                else
       
  4742                   *dp-- = 0xff;
       
  4743 
       
  4744                *dp-- = *sp--;
       
  4745                *dp-- = *sp--;
       
  4746                *dp-- = *sp--;
       
  4747             }
       
  4748          }
       
  4749          else if (row_info->bit_depth == 16)
       
  4750          {
       
  4751             png_byte red_high = (png_byte)((trans_color->red >> 8) & 0xff);
       
  4752             png_byte green_high = (png_byte)((trans_color->green >> 8) & 0xff);
       
  4753             png_byte blue_high = (png_byte)((trans_color->blue >> 8) & 0xff);
       
  4754             png_byte red_low = (png_byte)(trans_color->red & 0xff);
       
  4755             png_byte green_low = (png_byte)(trans_color->green & 0xff);
       
  4756             png_byte blue_low = (png_byte)(trans_color->blue & 0xff);
       
  4757             sp = row + row_info->rowbytes - 1;
       
  4758             dp = row + (png_size_t)(row_width << 3) - 1;
       
  4759             for (i = 0; i < row_width; i++)
       
  4760             {
       
  4761                if (*(sp - 5) == red_high &&
       
  4762                    *(sp - 4) == red_low &&
       
  4763                    *(sp - 3) == green_high &&
       
  4764                    *(sp - 2) == green_low &&
       
  4765                    *(sp - 1) == blue_high &&
       
  4766                    *(sp    ) == blue_low)
       
  4767                {
       
  4768                   *dp-- = 0;
       
  4769                   *dp-- = 0;
       
  4770                }
       
  4771 
       
  4772                else
       
  4773                {
       
  4774                   *dp-- = 0xff;
       
  4775                   *dp-- = 0xff;
       
  4776                }
       
  4777 
       
  4778                *dp-- = *sp--;
       
  4779                *dp-- = *sp--;
       
  4780                *dp-- = *sp--;
       
  4781                *dp-- = *sp--;
       
  4782                *dp-- = *sp--;
       
  4783                *dp-- = *sp--;
       
  4784             }
       
  4785          }
       
  4786          row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
       
  4787          row_info->channels = 4;
       
  4788          row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2);
       
  4789          row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
       
  4790       }
       
  4791    }
       
  4792 }
       
  4793 #endif
       
  4794 
       
  4795 #ifdef PNG_READ_EXPAND_16_SUPPORTED
       
  4796 /* If the bit depth is 8 and the colour type is not a palette type expand the
       
  4797  * whole row to 16 bits.  Has no effect otherwise.
       
  4798  */
       
  4799 void /* PRIVATE */
       
  4800 png_do_expand_16(png_row_infop row_info, png_bytep row)
       
  4801 {
       
  4802    if (row_info->bit_depth == 8 &&
       
  4803       row_info->color_type != PNG_COLOR_TYPE_PALETTE)
       
  4804    {
       
  4805       /* The row have a sequence of bytes containing [0..255] and we need
       
  4806        * to turn it into another row containing [0..65535], to do this we
       
  4807        * calculate:
       
  4808        *
       
  4809        *  (input / 255) * 65535
       
  4810        *
       
  4811        *  Which happens to be exactly input * 257 and this can be achieved
       
  4812        *  simply by byte replication in place (copying backwards).
       
  4813        */
       
  4814       png_byte *sp = row + row_info->rowbytes; /* source, last byte + 1 */
       
  4815       png_byte *dp = sp + row_info->rowbytes;  /* destination, end + 1 */
       
  4816       while (dp > sp)
       
  4817          dp[-2] = dp[-1] = *--sp, dp -= 2;
       
  4818 
       
  4819       row_info->rowbytes *= 2;
       
  4820       row_info->bit_depth = 16;
       
  4821       row_info->pixel_depth = (png_byte)(row_info->channels * 16);
       
  4822    }
       
  4823 }
       
  4824 #endif
       
  4825 
       
  4826 #ifdef PNG_READ_QUANTIZE_SUPPORTED
       
  4827 void /* PRIVATE */
       
  4828 png_do_quantize(png_row_infop row_info, png_bytep row,
       
  4829     png_const_bytep palette_lookup, png_const_bytep quantize_lookup)
       
  4830 {
       
  4831    png_bytep sp, dp;
       
  4832    png_uint_32 i;
       
  4833    png_uint_32 row_width=row_info->width;
       
  4834 
       
  4835    png_debug(1, "in png_do_quantize");
       
  4836 
       
  4837    if (row_info->bit_depth == 8)
       
  4838    {
       
  4839       if (row_info->color_type == PNG_COLOR_TYPE_RGB && palette_lookup)
       
  4840       {
       
  4841          int r, g, b, p;
       
  4842          sp = row;
       
  4843          dp = row;
       
  4844          for (i = 0; i < row_width; i++)
       
  4845          {
       
  4846             r = *sp++;
       
  4847             g = *sp++;
       
  4848             b = *sp++;
       
  4849 
       
  4850             /* This looks real messy, but the compiler will reduce
       
  4851              * it down to a reasonable formula.  For example, with
       
  4852              * 5 bits per color, we get:
       
  4853              * p = (((r >> 3) & 0x1f) << 10) |
       
  4854              *    (((g >> 3) & 0x1f) << 5) |
       
  4855              *    ((b >> 3) & 0x1f);
       
  4856              */
       
  4857             p = (((r >> (8 - PNG_QUANTIZE_RED_BITS)) &
       
  4858                 ((1 << PNG_QUANTIZE_RED_BITS) - 1)) <<
       
  4859                 (PNG_QUANTIZE_GREEN_BITS + PNG_QUANTIZE_BLUE_BITS)) |
       
  4860                 (((g >> (8 - PNG_QUANTIZE_GREEN_BITS)) &
       
  4861                 ((1 << PNG_QUANTIZE_GREEN_BITS) - 1)) <<
       
  4862                 (PNG_QUANTIZE_BLUE_BITS)) |
       
  4863                 ((b >> (8 - PNG_QUANTIZE_BLUE_BITS)) &
       
  4864                 ((1 << PNG_QUANTIZE_BLUE_BITS) - 1));
       
  4865 
       
  4866             *dp++ = palette_lookup[p];
       
  4867          }
       
  4868 
       
  4869          row_info->color_type = PNG_COLOR_TYPE_PALETTE;
       
  4870          row_info->channels = 1;
       
  4871          row_info->pixel_depth = row_info->bit_depth;
       
  4872          row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
       
  4873       }
       
  4874 
       
  4875       else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
       
  4876          palette_lookup != NULL)
       
  4877       {
       
  4878          int r, g, b, p;
       
  4879          sp = row;
       
  4880          dp = row;
       
  4881          for (i = 0; i < row_width; i++)
       
  4882          {
       
  4883             r = *sp++;
       
  4884             g = *sp++;
       
  4885             b = *sp++;
       
  4886             sp++;
       
  4887 
       
  4888             p = (((r >> (8 - PNG_QUANTIZE_RED_BITS)) &
       
  4889                 ((1 << PNG_QUANTIZE_RED_BITS) - 1)) <<
       
  4890                 (PNG_QUANTIZE_GREEN_BITS + PNG_QUANTIZE_BLUE_BITS)) |
       
  4891                 (((g >> (8 - PNG_QUANTIZE_GREEN_BITS)) &
       
  4892                 ((1 << PNG_QUANTIZE_GREEN_BITS) - 1)) <<
       
  4893                 (PNG_QUANTIZE_BLUE_BITS)) |
       
  4894                 ((b >> (8 - PNG_QUANTIZE_BLUE_BITS)) &
       
  4895                 ((1 << PNG_QUANTIZE_BLUE_BITS) - 1));
       
  4896 
       
  4897             *dp++ = palette_lookup[p];
       
  4898          }
       
  4899 
       
  4900          row_info->color_type = PNG_COLOR_TYPE_PALETTE;
       
  4901          row_info->channels = 1;
       
  4902          row_info->pixel_depth = row_info->bit_depth;
       
  4903          row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
       
  4904       }
       
  4905 
       
  4906       else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
       
  4907          quantize_lookup)
       
  4908       {
       
  4909          sp = row;
       
  4910 
       
  4911          for (i = 0; i < row_width; i++, sp++)
       
  4912          {
       
  4913             *sp = quantize_lookup[*sp];
       
  4914          }
       
  4915       }
       
  4916    }
       
  4917 }
       
  4918 #endif /* PNG_READ_QUANTIZE_SUPPORTED */
       
  4919 #endif /* PNG_READ_TRANSFORMS_SUPPORTED */
       
  4920 
       
  4921 #ifdef PNG_MNG_FEATURES_SUPPORTED
       
  4922 /* Undoes intrapixel differencing  */
       
  4923 void /* PRIVATE */
       
  4924 png_do_read_intrapixel(png_row_infop row_info, png_bytep row)
       
  4925 {
       
  4926    png_debug(1, "in png_do_read_intrapixel");
       
  4927 
       
  4928    if (
       
  4929        (row_info->color_type & PNG_COLOR_MASK_COLOR))
       
  4930    {
       
  4931       int bytes_per_pixel;
       
  4932       png_uint_32 row_width = row_info->width;
       
  4933 
       
  4934       if (row_info->bit_depth == 8)
       
  4935       {
       
  4936          png_bytep rp;
       
  4937          png_uint_32 i;
       
  4938 
       
  4939          if (row_info->color_type == PNG_COLOR_TYPE_RGB)
       
  4940             bytes_per_pixel = 3;
       
  4941 
       
  4942          else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
       
  4943             bytes_per_pixel = 4;
       
  4944 
       
  4945          else
       
  4946             return;
       
  4947 
       
  4948          for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
       
  4949          {
       
  4950             *(rp) = (png_byte)((256 + *rp + *(rp + 1)) & 0xff);
       
  4951             *(rp+2) = (png_byte)((256 + *(rp + 2) + *(rp + 1)) & 0xff);
       
  4952          }
       
  4953       }
       
  4954       else if (row_info->bit_depth == 16)
       
  4955       {
       
  4956          png_bytep rp;
       
  4957          png_uint_32 i;
       
  4958 
       
  4959          if (row_info->color_type == PNG_COLOR_TYPE_RGB)
       
  4960             bytes_per_pixel = 6;
       
  4961 
       
  4962          else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
       
  4963             bytes_per_pixel = 8;
       
  4964 
       
  4965          else
       
  4966             return;
       
  4967 
       
  4968          for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
       
  4969          {
       
  4970             png_uint_32 s0   = (*(rp    ) << 8) | *(rp + 1);
       
  4971             png_uint_32 s1   = (*(rp + 2) << 8) | *(rp + 3);
       
  4972             png_uint_32 s2   = (*(rp + 4) << 8) | *(rp + 5);
       
  4973             png_uint_32 red  = (png_uint_32)((s0 + s1 + 65536L) & 0xffffL);
       
  4974             png_uint_32 blue = (png_uint_32)((s2 + s1 + 65536L) & 0xffffL);
       
  4975             *(rp    ) = (png_byte)((red >> 8) & 0xff);
       
  4976             *(rp + 1) = (png_byte)(red & 0xff);
       
  4977             *(rp + 4) = (png_byte)((blue >> 8) & 0xff);
       
  4978             *(rp + 5) = (png_byte)(blue & 0xff);
       
  4979          }
       
  4980       }
       
  4981    }
       
  4982 }
       
  4983 #endif /* PNG_MNG_FEATURES_SUPPORTED */
       
  4984 #endif /* PNG_READ_SUPPORTED */