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