LCOV - code coverage report
Current view: directory - media/libpng - pngrtran.c (source / functions) Found Hit Coverage
Test: app.info Lines: 566 106 18.7 %
Date: 2012-06-02 Functions: 22 14 63.6 %

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

Generated by: LCOV version 1.7