fltk 1.3.0rc3
About: FLTK (Fast Light Tool Kit) is a cross-platform C++ GUI toolkit for UNIX/Linux (X11), Microsoft Windows, and MacOS X. Release candidate.
  SfR Fresh Dox: fltk-1.3.0rc3-source.tar.gz ("inofficial" and yet experimental doxygen-generated source code documentation)  

pngrtran.c

Go to the documentation of this file.
00001 
00002 /* pngrtran.c - transforms the data in a row for PNG readers
00003  *
00004  * Last changed in libpng 1.2.38 [July 16, 2009]
00005  * Copyright (c) 1998-2009 Glenn Randers-Pehrson
00006  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
00007  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
00008  *
00009  * This code is released under the libpng license.
00010  * For conditions of distribution and use, see the disclaimer
00011  * and license in png.h
00012  *
00013  * This file contains functions optionally called by an application
00014  * in order to tell libpng how to handle data when reading a PNG.
00015  * Transformations that are used in both reading and writing are
00016  * in pngtrans.c.
00017  */
00018 
00019 #define PNG_INTERNAL
00020 #include "png.h"
00021 #if defined(PNG_READ_SUPPORTED)
00022 
00023 /* Set the action on getting a CRC error for an ancillary or critical chunk. */
00024 void PNGAPI
00025 png_set_crc_action(png_structp png_ptr, int crit_action, int ancil_action)
00026 {
00027    png_debug(1, "in png_set_crc_action");
00028    /* Tell libpng how we react to CRC errors in critical chunks */
00029    if (png_ptr == NULL)
00030       return;
00031    switch (crit_action)
00032    {
00033       case PNG_CRC_NO_CHANGE:                        /* Leave setting as is */
00034          break;
00035 
00036       case PNG_CRC_WARN_USE:                               /* Warn/use data */
00037          png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
00038          png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE;
00039          break;
00040 
00041       case PNG_CRC_QUIET_USE:                             /* Quiet/use data */
00042          png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
00043          png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE |
00044                            PNG_FLAG_CRC_CRITICAL_IGNORE;
00045          break;
00046 
00047       case PNG_CRC_WARN_DISCARD:    /* Not a valid action for critical data */
00048          png_warning(png_ptr,
00049             "Can't discard critical data on CRC error.");
00050       case PNG_CRC_ERROR_QUIT:                                /* Error/quit */
00051 
00052       case PNG_CRC_DEFAULT:
00053       default:
00054          png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
00055          break;
00056    }
00057 
00058    switch (ancil_action)
00059    {
00060       case PNG_CRC_NO_CHANGE:                       /* Leave setting as is */
00061          break;
00062 
00063       case PNG_CRC_WARN_USE:                              /* Warn/use data */
00064          png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
00065          png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE;
00066          break;
00067 
00068       case PNG_CRC_QUIET_USE:                            /* Quiet/use data */
00069          png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
00070          png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE |
00071                            PNG_FLAG_CRC_ANCILLARY_NOWARN;
00072          break;
00073 
00074       case PNG_CRC_ERROR_QUIT:                               /* Error/quit */
00075          png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
00076          png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN;
00077          break;
00078 
00079       case PNG_CRC_WARN_DISCARD:                      /* Warn/discard data */
00080 
00081       case PNG_CRC_DEFAULT:
00082       default:
00083          png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
00084          break;
00085    }
00086 }
00087 
00088 #if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
00089     defined(PNG_FLOATING_POINT_SUPPORTED)
00090 /* Handle alpha and tRNS via a background color */
00091 void PNGAPI
00092 png_set_background(png_structp png_ptr,
00093    png_color_16p background_color, int background_gamma_code,
00094    int need_expand, double background_gamma)
00095 {
00096    png_debug(1, "in png_set_background");
00097    if (png_ptr == NULL)
00098       return;
00099    if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN)
00100    {
00101       png_warning(png_ptr, "Application must supply a known background gamma");
00102       return;
00103    }
00104 
00105    png_ptr->transformations |= PNG_BACKGROUND;
00106    png_memcpy(&(png_ptr->background), background_color,
00107       png_sizeof(png_color_16));
00108    png_ptr->background_gamma = (float)background_gamma;
00109    png_ptr->background_gamma_type = (png_byte)(background_gamma_code);
00110    png_ptr->transformations |= (need_expand ? PNG_BACKGROUND_EXPAND : 0);
00111 }
00112 #endif
00113 
00114 #if defined(PNG_READ_16_TO_8_SUPPORTED)
00115 /* Strip 16 bit depth files to 8 bit depth */
00116 void PNGAPI
00117 png_set_strip_16(png_structp png_ptr)
00118 {
00119    png_debug(1, "in png_set_strip_16");
00120    if (png_ptr == NULL)
00121       return;
00122    png_ptr->transformations |= PNG_16_TO_8;
00123 }
00124 #endif
00125 
00126 #if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
00127 void PNGAPI
00128 png_set_strip_alpha(png_structp png_ptr)
00129 {
00130    png_debug(1, "in png_set_strip_alpha");
00131    if (png_ptr == NULL)
00132       return;
00133    png_ptr->flags |= PNG_FLAG_STRIP_ALPHA;
00134 }
00135 #endif
00136 
00137 #if defined(PNG_READ_DITHER_SUPPORTED)
00138 /* Dither file to 8 bit.  Supply a palette, the current number
00139  * of elements in the palette, the maximum number of elements
00140  * allowed, and a histogram if possible.  If the current number
00141  * of colors is greater then the maximum number, the palette will be
00142  * modified to fit in the maximum number.  "full_dither" indicates
00143  * whether we need a dithering cube set up for RGB images, or if we
00144  * simply are reducing the number of colors in a paletted image.
00145  */
00146 
00147 typedef struct png_dsort_struct
00148 {
00149    struct png_dsort_struct FAR * next;
00150    png_byte left;
00151    png_byte right;
00152 } png_dsort;
00153 typedef png_dsort FAR *       png_dsortp;
00154 typedef png_dsort FAR * FAR * png_dsortpp;
00155 
00156 void PNGAPI
00157 png_set_dither(png_structp png_ptr, png_colorp palette,
00158    int num_palette, int maximum_colors, png_uint_16p histogram,
00159    int full_dither)
00160 {
00161    png_debug(1, "in png_set_dither");
00162    if (png_ptr == NULL)
00163       return;
00164    png_ptr->transformations |= PNG_DITHER;
00165 
00166    if (!full_dither)
00167    {
00168       int i;
00169 
00170       png_ptr->dither_index = (png_bytep)png_malloc(png_ptr,
00171          (png_uint_32)(num_palette * png_sizeof(png_byte)));
00172       for (i = 0; i < num_palette; i++)
00173          png_ptr->dither_index[i] = (png_byte)i;
00174    }
00175 
00176    if (num_palette > maximum_colors)
00177    {
00178       if (histogram != NULL)
00179       {
00180          /* This is easy enough, just throw out the least used colors.
00181           * Perhaps not the best solution, but good enough.
00182           */
00183 
00184          int i;
00185 
00186          /* Initialize an array to sort colors */
00187          png_ptr->dither_sort = (png_bytep)png_malloc(png_ptr,
00188             (png_uint_32)(num_palette * png_sizeof(png_byte)));
00189 
00190          /* Initialize the dither_sort array */
00191          for (i = 0; i < num_palette; i++)
00192             png_ptr->dither_sort[i] = (png_byte)i;
00193 
00194          /* Find the least used palette entries by starting a
00195           * bubble sort, and running it until we have sorted
00196           * out enough colors.  Note that we don't care about
00197           * sorting all the colors, just finding which are
00198           * least used.
00199           */
00200 
00201          for (i = num_palette - 1; i >= maximum_colors; i--)
00202          {
00203             int done; /* To stop early if the list is pre-sorted */
00204             int j;
00205 
00206             done = 1;
00207             for (j = 0; j < i; j++)
00208             {
00209                if (histogram[png_ptr->dither_sort[j]]
00210                    < histogram[png_ptr->dither_sort[j + 1]])
00211                {
00212                   png_byte t;
00213 
00214                   t = png_ptr->dither_sort[j];
00215                   png_ptr->dither_sort[j] = png_ptr->dither_sort[j + 1];
00216                   png_ptr->dither_sort[j + 1] = t;
00217                   done = 0;
00218                }
00219             }
00220             if (done)
00221                break;
00222          }
00223 
00224          /* Swap the palette around, and set up a table, if necessary */
00225          if (full_dither)
00226          {
00227             int j = num_palette;
00228 
00229             /* Put all the useful colors within the max, but don't
00230              * move the others.
00231              */
00232             for (i = 0; i < maximum_colors; i++)
00233             {
00234                if ((int)png_ptr->dither_sort[i] >= maximum_colors)
00235                {
00236                   do
00237                      j--;
00238                   while ((int)png_ptr->dither_sort[j] >= maximum_colors);
00239                   palette[i] = palette[j];
00240                }
00241             }
00242          }
00243          else
00244          {
00245             int j = num_palette;
00246 
00247             /* Move all the used colors inside the max limit, and
00248              * develop a translation table.
00249              */
00250             for (i = 0; i < maximum_colors; i++)
00251             {
00252                /* Only move the colors we need to */
00253                if ((int)png_ptr->dither_sort[i] >= maximum_colors)
00254                {
00255                   png_color tmp_color;
00256 
00257                   do
00258                      j--;
00259                   while ((int)png_ptr->dither_sort[j] >= maximum_colors);
00260 
00261                   tmp_color = palette[j];
00262                   palette[j] = palette[i];
00263                   palette[i] = tmp_color;
00264                   /* Indicate where the color went */
00265                   png_ptr->dither_index[j] = (png_byte)i;
00266                   png_ptr->dither_index[i] = (png_byte)j;
00267                }
00268             }
00269 
00270             /* Find closest color for those colors we are not using */
00271             for (i = 0; i < num_palette; i++)
00272             {
00273                if ((int)png_ptr->dither_index[i] >= maximum_colors)
00274                {
00275                   int min_d, k, min_k, d_index;
00276 
00277                   /* Find the closest color to one we threw out */
00278                   d_index = png_ptr->dither_index[i];
00279                   min_d = PNG_COLOR_DIST(palette[d_index], palette[0]);
00280                   for (k = 1, min_k = 0; k < maximum_colors; k++)
00281                   {
00282                      int d;
00283 
00284                      d = PNG_COLOR_DIST(palette[d_index], palette[k]);
00285 
00286                      if (d < min_d)
00287                      {
00288                         min_d = d;
00289                         min_k = k;
00290                      }
00291                   }
00292                   /* Point to closest color */
00293                   png_ptr->dither_index[i] = (png_byte)min_k;
00294                }
00295             }
00296          }
00297          png_free(png_ptr, png_ptr->dither_sort);
00298          png_ptr->dither_sort = NULL;
00299       }
00300       else
00301       {
00302          /* This is much harder to do simply (and quickly).  Perhaps
00303           * we need to go through a median cut routine, but those
00304           * don't always behave themselves with only a few colors
00305           * as input.  So we will just find the closest two colors,
00306           * and throw out one of them (chosen somewhat randomly).
00307           * [We don't understand this at all, so if someone wants to
00308           *  work on improving it, be our guest - AED, GRP]
00309           */
00310          int i;
00311          int max_d;
00312          int num_new_palette;
00313          png_dsortp t;
00314          png_dsortpp hash;
00315 
00316          t = NULL;
00317 
00318          /* Initialize palette index arrays */
00319          png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr,
00320             (png_uint_32)(num_palette * png_sizeof(png_byte)));
00321          png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr,
00322             (png_uint_32)(num_palette * png_sizeof(png_byte)));
00323 
00324          /* Initialize the sort array */
00325          for (i = 0; i < num_palette; i++)
00326          {
00327             png_ptr->index_to_palette[i] = (png_byte)i;
00328             png_ptr->palette_to_index[i] = (png_byte)i;
00329          }
00330 
00331          hash = (png_dsortpp)png_malloc(png_ptr, (png_uint_32)(769 *
00332             png_sizeof(png_dsortp)));
00333          png_memset(hash, 0, 769 * png_sizeof(png_dsortp));
00334 
00335          num_new_palette = num_palette;
00336 
00337          /* Initial wild guess at how far apart the farthest pixel
00338           * pair we will be eliminating will be.  Larger
00339           * numbers mean more areas will be allocated, Smaller
00340           * numbers run the risk of not saving enough data, and
00341           * having to do this all over again.
00342           *
00343           * I have not done extensive checking on this number.
00344           */
00345          max_d = 96;
00346 
00347          while (num_new_palette > maximum_colors)
00348          {
00349             for (i = 0; i < num_new_palette - 1; i++)
00350             {
00351                int j;
00352 
00353                for (j = i + 1; j < num_new_palette; j++)
00354                {
00355                   int d;
00356 
00357                   d = PNG_COLOR_DIST(palette[i], palette[j]);
00358 
00359                   if (d <= max_d)
00360                   {
00361 
00362                      t = (png_dsortp)png_malloc_warn(png_ptr,
00363                          (png_uint_32)(png_sizeof(png_dsort)));
00364                      if (t == NULL)
00365                          break;
00366                      t->next = hash[d];
00367                      t->left = (png_byte)i;
00368                      t->right = (png_byte)j;
00369                      hash[d] = t;
00370                   }
00371                }
00372                if (t == NULL)
00373                   break;
00374             }
00375 
00376             if (t != NULL)
00377             for (i = 0; i <= max_d; i++)
00378             {
00379                if (hash[i] != NULL)
00380                {
00381                   png_dsortp p;
00382 
00383                   for (p = hash[i]; p; p = p->next)
00384                   {
00385                      if ((int)png_ptr->index_to_palette[p->left]
00386                         < num_new_palette &&
00387                         (int)png_ptr->index_to_palette[p->right]
00388                         < num_new_palette)
00389                      {
00390                         int j, next_j;
00391 
00392                         if (num_new_palette & 0x01)
00393                         {
00394                            j = p->left;
00395                            next_j = p->right;
00396                         }
00397                         else
00398                         {
00399                            j = p->right;
00400                            next_j = p->left;
00401                         }
00402 
00403                         num_new_palette--;
00404                         palette[png_ptr->index_to_palette[j]]
00405                           = palette[num_new_palette];
00406                         if (!full_dither)
00407                         {
00408                            int k;
00409 
00410                            for (k = 0; k < num_palette; k++)
00411                            {
00412                               if (png_ptr->dither_index[k] ==
00413                                  png_ptr->index_to_palette[j])
00414                                  png_ptr->dither_index[k] =
00415                                     png_ptr->index_to_palette[next_j];
00416                               if ((int)png_ptr->dither_index[k] ==
00417                                  num_new_palette)
00418                                  png_ptr->dither_index[k] =
00419                                     png_ptr->index_to_palette[j];
00420                            }
00421                         }
00422 
00423                         png_ptr->index_to_palette[png_ptr->palette_to_index
00424                            [num_new_palette]] = png_ptr->index_to_palette[j];
00425                         png_ptr->palette_to_index[png_ptr->index_to_palette[j]]
00426                            = png_ptr->palette_to_index[num_new_palette];
00427 
00428                         png_ptr->index_to_palette[j] = (png_byte)num_new_palette;
00429                         png_ptr->palette_to_index[num_new_palette] = (png_byte)j;
00430                      }
00431                      if (num_new_palette <= maximum_colors)
00432                         break;
00433                   }
00434                   if (num_new_palette <= maximum_colors)
00435                      break;
00436                }
00437             }
00438 
00439             for (i = 0; i < 769; i++)
00440             {
00441                if (hash[i] != NULL)
00442                {
00443                   png_dsortp p = hash[i];
00444                   while (p)
00445                   {
00446                      t = p->next;
00447                      png_free(png_ptr, p);
00448                      p = t;
00449                   }
00450                }
00451                hash[i] = 0;
00452             }
00453             max_d += 96;
00454          }
00455          png_free(png_ptr, hash);
00456          png_free(png_ptr, png_ptr->palette_to_index);
00457          png_free(png_ptr, png_ptr->index_to_palette);
00458          png_ptr->palette_to_index = NULL;
00459          png_ptr->index_to_palette = NULL;
00460       }
00461       num_palette = maximum_colors;
00462    }
00463    if (png_ptr->palette == NULL)
00464    {
00465       png_ptr->palette = palette;
00466    }
00467    png_ptr->num_palette = (png_uint_16)num_palette;
00468 
00469    if (full_dither)
00470    {
00471       int i;
00472       png_bytep distance;
00473       int total_bits = PNG_DITHER_RED_BITS + PNG_DITHER_GREEN_BITS +
00474          PNG_DITHER_BLUE_BITS;
00475       int num_red = (1 << PNG_DITHER_RED_BITS);
00476       int num_green = (1 << PNG_DITHER_GREEN_BITS);
00477       int num_blue = (1 << PNG_DITHER_BLUE_BITS);
00478       png_size_t num_entries = ((png_size_t)1 << total_bits);
00479       png_ptr->palette_lookup = (png_bytep )png_malloc(png_ptr,
00480          (png_uint_32)(num_entries * png_sizeof(png_byte)));
00481       png_memset(png_ptr->palette_lookup, 0, num_entries *
00482          png_sizeof(png_byte));
00483 
00484       distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries *
00485          png_sizeof(png_byte)));
00486 
00487       png_memset(distance, 0xff, num_entries * png_sizeof(png_byte));
00488 
00489       for (i = 0; i < num_palette; i++)
00490       {
00491          int ir, ig, ib;
00492          int r = (palette[i].red >> (8 - PNG_DITHER_RED_BITS));
00493          int g = (palette[i].green >> (8 - PNG_DITHER_GREEN_BITS));
00494          int b = (palette[i].blue >> (8 - PNG_DITHER_BLUE_BITS));
00495 
00496          for (ir = 0; ir < num_red; ir++)
00497          {
00498             /* int dr = abs(ir - r); */
00499             int dr = ((ir > r) ? ir - r : r - ir);
00500             int index_r = (ir << (PNG_DITHER_BLUE_BITS + PNG_DITHER_GREEN_BITS));
00501 
00502             for (ig = 0; ig < num_green; ig++)
00503             {
00504                /* int dg = abs(ig - g); */
00505                int dg = ((ig > g) ? ig - g : g - ig);
00506                int dt = dr + dg;
00507                int dm = ((dr > dg) ? dr : dg);
00508                int index_g = index_r | (ig << PNG_DITHER_BLUE_BITS);
00509 
00510                for (ib = 0; ib < num_blue; ib++)
00511                {
00512                   int d_index = index_g | ib;
00513                   /* int db = abs(ib - b); */
00514                   int db = ((ib > b) ? ib - b : b - ib);
00515                   int dmax = ((dm > db) ? dm : db);
00516                   int d = dmax + dt + db;
00517 
00518                   if (d < (int)distance[d_index])
00519                   {
00520                      distance[d_index] = (png_byte)d;
00521                      png_ptr->palette_lookup[d_index] = (png_byte)i;
00522                   }
00523                }
00524             }
00525          }
00526       }
00527 
00528       png_free(png_ptr, distance);
00529    }
00530 }
00531 #endif
00532 
00533 #if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
00534 /* Transform the image from the file_gamma to the screen_gamma.  We
00535  * only do transformations on images where the file_gamma and screen_gamma
00536  * are not close reciprocals, otherwise it slows things down slightly, and
00537  * also needlessly introduces small errors.
00538  *
00539  * We will turn off gamma transformation later if no semitransparent entries
00540  * are present in the tRNS array for palette images.  We can't do it here
00541  * because we don't necessarily have the tRNS chunk yet.
00542  */
00543 void PNGAPI
00544 png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma)
00545 {
00546    png_debug(1, "in png_set_gamma");
00547    if (png_ptr == NULL)
00548       return;
00549    if ((fabs(scrn_gamma * file_gamma - 1.0) > PNG_GAMMA_THRESHOLD) ||
00550        (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) ||
00551        (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))
00552      png_ptr->transformations |= PNG_GAMMA;
00553    png_ptr->gamma = (float)file_gamma;
00554    png_ptr->screen_gamma = (float)scrn_gamma;
00555 }
00556 #endif
00557 
00558 #if defined(PNG_READ_EXPAND_SUPPORTED)
00559 /* Expand paletted images to RGB, expand grayscale images of
00560  * less than 8-bit depth to 8-bit depth, and expand tRNS chunks
00561  * to alpha channels.
00562  */
00563 void PNGAPI
00564 png_set_expand(png_structp png_ptr)
00565 {
00566    png_debug(1, "in png_set_expand");
00567    if (png_ptr == NULL)
00568       return;
00569    png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
00570    png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
00571 }
00572 
00573 /* GRR 19990627:  the following three functions currently are identical
00574  *  to png_set_expand().  However, it is entirely reasonable that someone
00575  *  might wish to expand an indexed image to RGB but *not* expand a single,
00576  *  fully transparent palette entry to a full alpha channel--perhaps instead
00577  *  convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace
00578  *  the transparent color with a particular RGB value, or drop tRNS entirely.
00579  *  IOW, a future version of the library may make the transformations flag
00580  *  a bit more fine-grained, with separate bits for each of these three
00581  *  functions.
00582  *
00583  *  More to the point, these functions make it obvious what libpng will be
00584  *  doing, whereas "expand" can (and does) mean any number of things.
00585  *
00586  *  GRP 20060307: In libpng-1.4.0, png_set_gray_1_2_4_to_8() was modified
00587  *  to expand only the sample depth but not to expand the tRNS to alpha.
00588  */
00589 
00590 /* Expand paletted images to RGB. */
00591 void PNGAPI
00592 png_set_palette_to_rgb(png_structp png_ptr)
00593 {
00594    png_debug(1, "in png_set_palette_to_rgb");
00595    if (png_ptr == NULL)
00596       return;
00597    png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
00598    png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
00599 }
00600 
00601 #if !defined(PNG_1_0_X)
00602 /* Expand grayscale images of less than 8-bit depth to 8 bits. */
00603 void PNGAPI
00604 png_set_expand_gray_1_2_4_to_8(png_structp png_ptr)
00605 {
00606    png_debug(1, "in png_set_expand_gray_1_2_4_to_8");
00607    if (png_ptr == NULL)
00608       return;
00609    png_ptr->transformations |= PNG_EXPAND;
00610    png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
00611 }
00612 #endif
00613 
00614 #if defined(PNG_1_0_X) || defined(PNG_1_2_X)
00615 /* Expand grayscale images of less than 8-bit depth to 8 bits. */
00616 /* Deprecated as of libpng-1.2.9 */
00617 void PNGAPI
00618 png_set_gray_1_2_4_to_8(png_structp png_ptr)
00619 {
00620    png_debug(1, "in png_set_gray_1_2_4_to_8");
00621    if (png_ptr == NULL)
00622       return;
00623    png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
00624 }
00625 #endif
00626 
00627 
00628 /* Expand tRNS chunks to alpha channels. */
00629 void PNGAPI
00630 png_set_tRNS_to_alpha(png_structp png_ptr)
00631 {
00632    png_debug(1, "in png_set_tRNS_to_alpha");
00633    png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
00634    png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
00635 }
00636 #endif /* defined(PNG_READ_EXPAND_SUPPORTED) */
00637 
00638 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
00639 void PNGAPI
00640 png_set_gray_to_rgb(png_structp png_ptr)
00641 {
00642    png_debug(1, "in png_set_gray_to_rgb");
00643    png_ptr->transformations |= PNG_GRAY_TO_RGB;
00644    png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
00645 }
00646 #endif
00647 
00648 #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
00649 #if defined(PNG_FLOATING_POINT_SUPPORTED)
00650 /* Convert a RGB image to a grayscale of the same width.  This allows us,
00651  * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image.
00652  */
00653 
00654 void PNGAPI
00655 png_set_rgb_to_gray(png_structp png_ptr, int error_action, double red,
00656    double green)
00657 {
00658    int red_fixed = (int)((float)red*100000.0 + 0.5);
00659    int green_fixed = (int)((float)green*100000.0 + 0.5);
00660    if (png_ptr == NULL)
00661       return;
00662    png_set_rgb_to_gray_fixed(png_ptr, error_action, red_fixed, green_fixed);
00663 }
00664 #endif
00665 
00666 void PNGAPI
00667 png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action,
00668    png_fixed_point red, png_fixed_point green)
00669 {
00670    png_debug(1, "in png_set_rgb_to_gray");
00671    if (png_ptr == NULL)
00672       return;
00673    switch(error_action)
00674    {
00675       case 1: png_ptr->transformations |= PNG_RGB_TO_GRAY;
00676               break;
00677 
00678       case 2: png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN;
00679               break;
00680 
00681       case 3: png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR;
00682    }
00683    if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
00684 #if defined(PNG_READ_EXPAND_SUPPORTED)
00685       png_ptr->transformations |= PNG_EXPAND;
00686 #else
00687    {
00688       png_warning(png_ptr,
00689         "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED.");
00690       png_ptr->transformations &= ~PNG_RGB_TO_GRAY;
00691    }
00692 #endif
00693    {
00694       png_uint_16 red_int, green_int;
00695       if (red < 0 || green < 0)
00696       {
00697          red_int   =  6968; /* .212671 * 32768 + .5 */
00698          green_int = 23434; /* .715160 * 32768 + .5 */
00699       }
00700       else if (red + green < 100000L)
00701       {
00702          red_int = (png_uint_16)(((png_uint_32)red*32768L)/100000L);
00703          green_int = (png_uint_16)(((png_uint_32)green*32768L)/100000L);
00704       }
00705       else
00706       {
00707          png_warning(png_ptr, "ignoring out of range rgb_to_gray coefficients");
00708          red_int   =  6968;
00709          green_int = 23434;
00710       }
00711       png_ptr->rgb_to_gray_red_coeff   = red_int;
00712       png_ptr->rgb_to_gray_green_coeff = green_int;
00713       png_ptr->rgb_to_gray_blue_coeff  =
00714          (png_uint_16)(32768 - red_int - green_int);
00715    }
00716 }
00717 #endif
00718 
00719 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
00720     defined(PNG_LEGACY_SUPPORTED) || \
00721     defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
00722 void PNGAPI
00723 png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr
00724    read_user_transform_fn)
00725 {
00726    png_debug(1, "in png_set_read_user_transform_fn");
00727    if (png_ptr == NULL)
00728       return;
00729 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
00730    png_ptr->transformations |= PNG_USER_TRANSFORM;
00731    png_ptr->read_user_transform_fn = read_user_transform_fn;
00732 #endif
00733 #ifdef PNG_LEGACY_SUPPORTED
00734    if (read_user_transform_fn)
00735       png_warning(png_ptr,
00736         "This version of libpng does not support user transforms");
00737 #endif
00738 }
00739 #endif
00740 
00741 /* Initialize everything needed for the read.  This includes modifying
00742  * the palette.
00743  */
00744 void /* PRIVATE */
00745 png_init_read_transformations(png_structp png_ptr)
00746 {
00747    png_debug(1, "in png_init_read_transformations");
00748 #if defined(PNG_USELESS_TESTS_SUPPORTED)
00749    if (png_ptr != NULL)
00750 #endif
00751   {
00752 #if defined(PNG_READ_BACKGROUND_SUPPORTED) || defined(PNG_READ_SHIFT_SUPPORTED) \
00753  || defined(PNG_READ_GAMMA_SUPPORTED)
00754    int color_type = png_ptr->color_type;
00755 #endif
00756 
00757 #if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
00758 
00759 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
00760    /* Detect gray background and attempt to enable optimization
00761     * for gray --> RGB case
00762     *
00763     * Note:  if PNG_BACKGROUND_EXPAND is set and color_type is either RGB or
00764     * RGB_ALPHA (in which case need_expand is superfluous anyway), the
00765     * background color might actually be gray yet not be flagged as such.
00766     * This is not a problem for the current code, which uses
00767     * PNG_BACKGROUND_IS_GRAY only to decide when to do the
00768     * png_do_gray_to_rgb() transformation.
00769     */
00770    if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
00771        !(color_type & PNG_COLOR_MASK_COLOR))
00772    {
00773           png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
00774    } else if ((png_ptr->transformations & PNG_BACKGROUND) &&
00775               !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
00776               (png_ptr->transformations & PNG_GRAY_TO_RGB) &&
00777               png_ptr->background.red == png_ptr->background.green &&
00778               png_ptr->background.red == png_ptr->background.blue)
00779    {
00780           png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
00781           png_ptr->background.gray = png_ptr->background.red;
00782    }
00783 #endif
00784 
00785    if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
00786        (png_ptr->transformations & PNG_EXPAND))
00787    {
00788       if (!(color_type & PNG_COLOR_MASK_COLOR))  /* i.e., GRAY or GRAY_ALPHA */
00789       {
00790          /* Expand background and tRNS chunks */
00791          switch (png_ptr->bit_depth)
00792          {
00793             case 1:
00794                png_ptr->background.gray *= (png_uint_16)0xff;
00795                png_ptr->background.red = png_ptr->background.green
00796                  =  png_ptr->background.blue = png_ptr->background.gray;
00797                if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
00798                {
00799                  png_ptr->trans_values.gray *= (png_uint_16)0xff;
00800                  png_ptr->trans_values.red = png_ptr->trans_values.green
00801                    = png_ptr->trans_values.blue = png_ptr->trans_values.gray;
00802                }
00803                break;
00804 
00805             case 2:
00806                png_ptr->background.gray *= (png_uint_16)0x55;
00807                png_ptr->background.red = png_ptr->background.green
00808                  = png_ptr->background.blue = png_ptr->background.gray;
00809                if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
00810                {
00811                  png_ptr->trans_values.gray *= (png_uint_16)0x55;
00812                  png_ptr->trans_values.red = png_ptr->trans_values.green
00813                    = png_ptr->trans_values.blue = png_ptr->trans_values.gray;
00814                }
00815                break;
00816 
00817             case 4:
00818                png_ptr->background.gray *= (png_uint_16)0x11;
00819                png_ptr->background.red = png_ptr->background.green
00820                  = png_ptr->background.blue = png_ptr->background.gray;
00821                if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
00822                {
00823                  png_ptr->trans_values.gray *= (png_uint_16)0x11;
00824                  png_ptr->trans_values.red = png_ptr->trans_values.green
00825                    = png_ptr->trans_values.blue = png_ptr->trans_values.gray;
00826                }
00827                break;
00828 
00829             case 8:
00830 
00831             case 16:
00832                png_ptr->background.red = png_ptr->background.green
00833                  = png_ptr->background.blue = png_ptr->background.gray;
00834                break;
00835          }
00836       }
00837       else if (color_type == PNG_COLOR_TYPE_PALETTE)
00838       {
00839          png_ptr->background.red   =
00840             png_ptr->palette[png_ptr->background.index].red;
00841          png_ptr->background.green =
00842             png_ptr->palette[png_ptr->background.index].green;
00843          png_ptr->background.blue  =
00844             png_ptr->palette[png_ptr->background.index].blue;
00845 
00846 #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
00847         if (png_ptr->transformations & PNG_INVERT_ALPHA)
00848         {
00849 #if defined(PNG_READ_EXPAND_SUPPORTED)
00850            if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
00851 #endif
00852            {
00853            /* Invert the alpha channel (in tRNS) unless the pixels are
00854             * going to be expanded, in which case leave it for later
00855             */
00856               int i, istop;
00857               istop=(int)png_ptr->num_trans;
00858               for (i=0; i<istop; i++)
00859                  png_ptr->trans[i] = (png_byte)(255 - png_ptr->trans[i]);
00860            }
00861         }
00862 #endif
00863 
00864       }
00865    }
00866 #endif
00867 
00868 #if defined(PNG_READ_BACKGROUND_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
00869    png_ptr->background_1 = png_ptr->background;
00870 #endif
00871 #if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
00872 
00873    if ((color_type == PNG_COLOR_TYPE_PALETTE && png_ptr->num_trans != 0)
00874        && (fabs(png_ptr->screen_gamma * png_ptr->gamma - 1.0)
00875          < PNG_GAMMA_THRESHOLD))
00876    {
00877     int i, k;
00878     k=0;
00879     for (i=0; i<png_ptr->num_trans; i++)
00880     {
00881       if (png_ptr->trans[i] != 0 && png_ptr->trans[i] != 0xff)
00882         k=1; /* Partial transparency is present */
00883     }
00884     if (k == 0)
00885       png_ptr->transformations &= ~PNG_GAMMA;
00886    }
00887 
00888    if ((png_ptr->transformations & (PNG_GAMMA | PNG_RGB_TO_GRAY)) &&
00889         png_ptr->gamma != 0.0)
00890    {
00891       png_build_gamma_table(png_ptr);
00892 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
00893       if (png_ptr->transformations & PNG_BACKGROUND)
00894       {
00895          if (color_type == PNG_COLOR_TYPE_PALETTE)
00896          {
00897            /* Could skip if no transparency */
00898             png_color back, back_1;
00899             png_colorp palette = png_ptr->palette;
00900             int num_palette = png_ptr->num_palette;
00901             int i;
00902             if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
00903             {
00904                back.red = png_ptr->gamma_table[png_ptr->background.red];
00905                back.green = png_ptr->gamma_table[png_ptr->background.green];
00906                back.blue = png_ptr->gamma_table[png_ptr->background.blue];
00907 
00908                back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
00909                back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
00910                back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
00911             }
00912             else
00913             {
00914                double g, gs;
00915 
00916                switch (png_ptr->background_gamma_type)
00917                {
00918                   case PNG_BACKGROUND_GAMMA_SCREEN:
00919                      g = (png_ptr->screen_gamma);
00920                      gs = 1.0;
00921                      break;
00922 
00923                   case PNG_BACKGROUND_GAMMA_FILE:
00924                      g = 1.0 / (png_ptr->gamma);
00925                      gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
00926                      break;
00927 
00928                   case PNG_BACKGROUND_GAMMA_UNIQUE:
00929                      g = 1.0 / (png_ptr->background_gamma);
00930                      gs = 1.0 / (png_ptr->background_gamma *
00931                                  png_ptr->screen_gamma);
00932                      break;
00933                   default:
00934                      g = 1.0;    /* back_1 */
00935                      gs = 1.0;   /* back */
00936                }
00937 
00938                if ( fabs(gs - 1.0) < PNG_GAMMA_THRESHOLD)
00939                {
00940                   back.red   = (png_byte)png_ptr->background.red;
00941                   back.green = (png_byte)png_ptr->background.green;
00942                   back.blue  = (png_byte)png_ptr->background.blue;
00943                }
00944                else
00945                {
00946                   back.red = (png_byte)(pow(
00947                      (double)png_ptr->background.red/255, gs) * 255.0 + .5);
00948                   back.green = (png_byte)(pow(
00949                      (double)png_ptr->background.green/255, gs) * 255.0 + .5);
00950                   back.blue = (png_byte)(pow(
00951                      (double)png_ptr->background.blue/255, gs) * 255.0 + .5);
00952                }
00953 
00954                back_1.red = (png_byte)(pow(
00955                   (double)png_ptr->background.red/255, g) * 255.0 + .5);
00956                back_1.green = (png_byte)(pow(
00957                   (double)png_ptr->background.green/255, g) * 255.0 + .5);
00958                back_1.blue = (png_byte)(pow(
00959                   (double)png_ptr->background.blue/255, g) * 255.0 + .5);
00960             }
00961             for (i = 0; i < num_palette; i++)
00962             {
00963                if (i < (int)png_ptr->num_trans && png_ptr->trans[i] != 0xff)
00964                {
00965                   if (png_ptr->trans[i] == 0)
00966                   {
00967                      palette[i] = back;
00968                   }
00969                   else /* if (png_ptr->trans[i] != 0xff) */
00970                   {
00971                      png_byte v, w;
00972 
00973                      v = png_ptr->gamma_to_1[palette[i].red];
00974                      png_composite(w, v, png_ptr->trans[i], back_1.red);
00975                      palette[i].red = png_ptr->gamma_from_1[w];
00976 
00977                      v = png_ptr->gamma_to_1[palette[i].green];
00978                      png_composite(w, v, png_ptr->trans[i], back_1.green);
00979                      palette[i].green = png_ptr->gamma_from_1[w];
00980 
00981                      v = png_ptr->gamma_to_1[palette[i].blue];
00982                      png_composite(w, v, png_ptr->trans[i], back_1.blue);
00983                      palette[i].blue = png_ptr->gamma_from_1[w];
00984                   }
00985                }
00986                else
00987                {
00988                   palette[i].red = png_ptr->gamma_table[palette[i].red];
00989                   palette[i].green = png_ptr->gamma_table[palette[i].green];
00990                   palette[i].blue = png_ptr->gamma_table[palette[i].blue];
00991                }
00992             }
00993             /* Prevent the transformations being done again, and make sure
00994              * that the now spurious alpha channel is stripped - the code
00995              * has just reduced background composition and gamma correction
00996              * to a simple alpha channel strip.
00997              */
00998             png_ptr->transformations &= ~PNG_BACKGROUND;
00999             png_ptr->transformations &= ~PNG_GAMMA;
01000             png_ptr->transformations |= PNG_STRIP_ALPHA;
01001          }
01002          /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */
01003          else
01004          /* color_type != PNG_COLOR_TYPE_PALETTE */
01005          {
01006             double m = (double)(((png_uint_32)1 << png_ptr->bit_depth) - 1);
01007             double g = 1.0;
01008             double gs = 1.0;
01009 
01010             switch (png_ptr->background_gamma_type)
01011             {
01012                case PNG_BACKGROUND_GAMMA_SCREEN:
01013                   g = (png_ptr->screen_gamma);
01014                   gs = 1.0;
01015                   break;
01016 
01017                case PNG_BACKGROUND_GAMMA_FILE:
01018                   g = 1.0 / (png_ptr->gamma);
01019                   gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
01020                   break;
01021 
01022                case PNG_BACKGROUND_GAMMA_UNIQUE:
01023                   g = 1.0 / (png_ptr->background_gamma);
01024                   gs = 1.0 / (png_ptr->background_gamma *
01025                      png_ptr->screen_gamma);
01026                   break;
01027             }
01028 
01029             png_ptr->background_1.gray = (png_uint_16)(pow(
01030                (double)png_ptr->background.gray / m, g) * m + .5);
01031             png_ptr->background.gray = (png_uint_16)(pow(
01032                (double)png_ptr->background.gray / m, gs) * m + .5);
01033 
01034             if ((png_ptr->background.red != png_ptr->background.green) ||
01035                 (png_ptr->background.red != png_ptr->background.blue) ||
01036                 (png_ptr->background.red != png_ptr->background.gray))
01037             {
01038                /* RGB or RGBA with color background */
01039                png_ptr->background_1.red = (png_uint_16)(pow(
01040                   (double)png_ptr->background.red / m, g) * m + .5);
01041                png_ptr->background_1.green = (png_uint_16)(pow(
01042                   (double)png_ptr->background.green / m, g) * m + .5);
01043                png_ptr->background_1.blue = (png_uint_16)(pow(
01044                   (double)png_ptr->background.blue / m, g) * m + .5);
01045                png_ptr->background.red = (png_uint_16)(pow(
01046                   (double)png_ptr->background.red / m, gs) * m + .5);
01047                png_ptr->background.green = (png_uint_16)(pow(
01048                   (double)png_ptr->background.green / m, gs) * m + .5);
01049                png_ptr->background.blue = (png_uint_16)(pow(
01050                   (double)png_ptr->background.blue / m, gs) * m + .5);
01051             }
01052             else
01053             {
01054                /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */
01055                png_ptr->background_1.red = png_ptr->background_1.green
01056                  = png_ptr->background_1.blue = png_ptr->background_1.gray;
01057                png_ptr->background.red = png_ptr->background.green
01058                  = png_ptr->background.blue = png_ptr->background.gray;
01059             }
01060          }
01061       }
01062       else
01063       /* Transformation does not include PNG_BACKGROUND */
01064 #endif /* PNG_READ_BACKGROUND_SUPPORTED */
01065       if (color_type == PNG_COLOR_TYPE_PALETTE)
01066       {
01067          png_colorp palette = png_ptr->palette;
01068          int num_palette = png_ptr->num_palette;
01069          int i;
01070 
01071          for (i = 0; i < num_palette; i++)
01072          {
01073             palette[i].red = png_ptr->gamma_table[palette[i].red];
01074             palette[i].green = png_ptr->gamma_table[palette[i].green];
01075             palette[i].blue = png_ptr->gamma_table[palette[i].blue];
01076          }
01077 
01078          /* Done the gamma correction. */
01079          png_ptr->transformations &= ~PNG_GAMMA;
01080       }
01081    }
01082 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
01083    else
01084 #endif
01085 #endif /* PNG_READ_GAMMA_SUPPORTED && PNG_FLOATING_POINT_SUPPORTED */
01086 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
01087    /* No GAMMA transformation */
01088    if ((png_ptr->transformations & PNG_BACKGROUND) &&
01089        (color_type == PNG_COLOR_TYPE_PALETTE))
01090    {
01091       int i;
01092       int istop = (int)png_ptr->num_trans;
01093       png_color back;
01094       png_colorp palette = png_ptr->palette;
01095 
01096       back.red   = (png_byte)png_ptr->background.red;
01097       back.green = (png_byte)png_ptr->background.green;
01098       back.blue  = (png_byte)png_ptr->background.blue;
01099 
01100       for (i = 0; i < istop; i++)
01101       {
01102          if (png_ptr->trans[i] == 0)
01103          {
01104             palette[i] = back;
01105          }
01106          else if (png_ptr->trans[i] != 0xff)
01107          {
01108             /* The png_composite() macro is defined in png.h */
01109             png_composite(palette[i].red, palette[i].red,
01110                png_ptr->trans[i], back.red);
01111             png_composite(palette[i].green, palette[i].green,
01112                png_ptr->trans[i], back.green);
01113             png_composite(palette[i].blue, palette[i].blue,
01114                png_ptr->trans[i], back.blue);
01115          }
01116       }
01117 
01118       /* Handled alpha, still need to strip the channel. */
01119       png_ptr->transformations &= ~PNG_BACKGROUND;
01120       png_ptr->transformations |= PNG_STRIP_ALPHA;
01121    }
01122 #endif /* PNG_READ_BACKGROUND_SUPPORTED */
01123 
01124 #if defined(PNG_READ_SHIFT_SUPPORTED)
01125    if ((png_ptr->transformations & PNG_SHIFT) &&
01126       (color_type == PNG_COLOR_TYPE_PALETTE))
01127    {
01128       png_uint_16 i;
01129       png_uint_16 istop = png_ptr->num_palette;
01130       int sr = 8 - png_ptr->sig_bit.red;
01131       int sg = 8 - png_ptr->sig_bit.green;
01132       int sb = 8 - png_ptr->sig_bit.blue;
01133 
01134       if (sr < 0 || sr > 8)
01135          sr = 0;
01136       if (sg < 0 || sg > 8)
01137          sg = 0;
01138       if (sb < 0 || sb > 8)
01139          sb = 0;
01140       for (i = 0; i < istop; i++)
01141       {
01142          png_ptr->palette[i].red >>= sr;
01143          png_ptr->palette[i].green >>= sg;
01144          png_ptr->palette[i].blue >>= sb;
01145       }
01146    }
01147 #endif  /* PNG_READ_SHIFT_SUPPORTED */
01148  }
01149 #if !defined(PNG_READ_GAMMA_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) \
01150  && !defined(PNG_READ_BACKGROUND_SUPPORTED)
01151    if (png_ptr)
01152       return;
01153 #endif
01154 }
01155 
01156 /* Modify the info structure to reflect the transformations.  The
01157  * info should be updated so a PNG file could be written with it,
01158  * assuming the transformations result in valid PNG data.
01159  */
01160 void /* PRIVATE */
01161 png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
01162 {
01163    png_debug(1, "in png_read_transform_info");
01164 #if defined(PNG_READ_EXPAND_SUPPORTED)
01165    if (png_ptr->transformations & PNG_EXPAND)
01166    {
01167       if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
01168       {
01169          if (png_ptr->num_trans &&
01170               (png_ptr->transformations & PNG_EXPAND_tRNS))
01171             info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
01172          else
01173             info_ptr->color_type = PNG_COLOR_TYPE_RGB;
01174          info_ptr->bit_depth = 8;
01175          info_ptr->num_trans = 0;
01176       }
01177       else
01178       {
01179          if (png_ptr->num_trans)
01180          {
01181             if (png_ptr->transformations & PNG_EXPAND_tRNS)
01182               info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
01183          }
01184          if (info_ptr->bit_depth < 8)
01185             info_ptr->bit_depth = 8;
01186          info_ptr->num_trans = 0;
01187       }
01188    }
01189 #endif
01190 
01191 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
01192    if (png_ptr->transformations & PNG_BACKGROUND)
01193    {
01194       info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
01195       info_ptr->num_trans = 0;
01196       info_ptr->background = png_ptr->background;
01197    }
01198 #endif
01199 
01200 #if defined(PNG_READ_GAMMA_SUPPORTED)
01201    if (png_ptr->transformations & PNG_GAMMA)
01202    {
01203 #ifdef PNG_FLOATING_POINT_SUPPORTED
01204       info_ptr->gamma = png_ptr->gamma;
01205 #endif
01206 #ifdef PNG_FIXED_POINT_SUPPORTED
01207       info_ptr->int_gamma = png_ptr->int_gamma;
01208 #endif
01209    }
01210 #endif
01211 
01212 #if defined(PNG_READ_16_TO_8_SUPPORTED)
01213    if ((png_ptr->transformations & PNG_16_TO_8) && (info_ptr->bit_depth == 16))
01214       info_ptr->bit_depth = 8;
01215 #endif
01216 
01217 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
01218    if (png_ptr->transformations & PNG_GRAY_TO_RGB)
01219       info_ptr->color_type |= PNG_COLOR_MASK_COLOR;
01220 #endif
01221 
01222 #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
01223    if (png_ptr->transformations & PNG_RGB_TO_GRAY)
01224       info_ptr->color_type &= ~PNG_COLOR_MASK_COLOR;
01225 #endif
01226 
01227 #if defined(PNG_READ_DITHER_SUPPORTED)
01228    if (png_ptr->transformations & PNG_DITHER)
01229    {
01230       if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
01231           (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) &&
01232           png_ptr->palette_lookup && info_ptr->bit_depth == 8)
01233       {
01234          info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
01235       }
01236    }
01237 #endif
01238 
01239 #if defined(PNG_READ_PACK_SUPPORTED)
01240    if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8))
01241       info_ptr->bit_depth = 8;
01242 #endif
01243 
01244    if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
01245       info_ptr->channels = 1;
01246    else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
01247       info_ptr->channels = 3;
01248    else
01249       info_ptr->channels = 1;
01250 
01251 #if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
01252    if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA)
01253       info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
01254 #endif
01255 
01256    if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
01257       info_ptr->channels++;
01258 
01259 #if defined(PNG_READ_FILLER_SUPPORTED)
01260    /* STRIP_ALPHA and FILLER allowed:  MASK_ALPHA bit stripped above */
01261    if ((png_ptr->transformations & PNG_FILLER) &&
01262        ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
01263        (info_ptr->color_type == PNG_COLOR_TYPE_GRAY)))
01264    {
01265       info_ptr->channels++;
01266       /* If adding a true alpha channel not just filler */
01267 #if !defined(PNG_1_0_X)
01268       if (png_ptr->transformations & PNG_ADD_ALPHA)
01269         info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
01270 #endif
01271    }
01272 #endif
01273 
01274 #if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \
01275 defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
01276    if (png_ptr->transformations & PNG_USER_TRANSFORM)
01277      {
01278        if (info_ptr->bit_depth < png_ptr->user_transform_depth)
01279          info_ptr->bit_depth = png_ptr->user_transform_depth;
01280        if (info_ptr->channels < png_ptr->user_transform_channels)
01281          info_ptr->channels = png_ptr->user_transform_channels;
01282      }
01283 #endif
01284 
01285    info_ptr->pixel_depth = (png_byte)(info_ptr->channels *
01286       info_ptr->bit_depth);
01287 
01288    info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, info_ptr->width);
01289 
01290 #if !defined(PNG_READ_EXPAND_SUPPORTED)
01291    if (png_ptr)
01292       return;
01293 #endif
01294 }
01295 
01296 /* Transform the row.  The order of transformations is significant,
01297  * and is very touchy.  If you add a transformation, take care to
01298  * decide how it fits in with the other transformations here.
01299  */
01300 void /* PRIVATE */
01301 png_do_read_transformations(png_structp png_ptr)
01302 {
01303    png_debug(1, "in png_do_read_transformations");
01304    if (png_ptr->row_buf == NULL)
01305    {
01306 #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
01307       char msg[50];
01308 
01309       png_snprintf2(msg, 50,
01310          "NULL row buffer for row %ld, pass %d", (long)png_ptr->row_number,
01311          png_ptr->pass);
01312       png_error(png_ptr, msg);
01313 #else
01314       png_error(png_ptr, "NULL row buffer");
01315 #endif
01316    }
01317 #ifdef PNG_WARN_UNINITIALIZED_ROW
01318    if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
01319       /* Application has failed to call either png_read_start_image()
01320        * or png_read_update_info() after setting transforms that expand
01321        * pixels.  This check added to libpng-1.2.19
01322        */
01323 #if (PNG_WARN_UNINITIALIZED_ROW==1)
01324       png_error(png_ptr, "Uninitialized row");
01325 #else
01326       png_warning(png_ptr, "Uninitialized row");
01327 #endif
01328 #endif
01329 
01330 #if defined(PNG_READ_EXPAND_SUPPORTED)
01331    if (png_ptr->transformations & PNG_EXPAND)
01332    {
01333       if (png_ptr->row_info.color_type == PNG_COLOR_TYPE_PALETTE)
01334       {
01335          png_do_expand_palette(&(png_ptr->row_info), png_ptr->row_buf + 1,
01336             png_ptr->palette, png_ptr->trans, png_ptr->num_trans);
01337       }
01338       else
01339       {
01340          if (png_ptr->num_trans &&
01341              (png_ptr->transformations & PNG_EXPAND_tRNS))
01342             png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
01343                &(png_ptr->trans_values));
01344          else
01345             png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
01346                NULL);
01347       }
01348    }
01349 #endif
01350 
01351 #if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
01352    if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA)
01353       png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
01354          PNG_FLAG_FILLER_AFTER | (png_ptr->flags & PNG_FLAG_STRIP_ALPHA));
01355 #endif
01356 
01357 #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
01358    if (png_ptr->transformations & PNG_RGB_TO_GRAY)
01359    {
01360       int rgb_error =
01361          png_do_rgb_to_gray(png_ptr, &(png_ptr->row_info), png_ptr->row_buf + 1);
01362       if (rgb_error)
01363       {
01364          png_ptr->rgb_to_gray_status=1;
01365          if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
01366              PNG_RGB_TO_GRAY_WARN)
01367             png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel");
01368          if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
01369              PNG_RGB_TO_GRAY_ERR)
01370             png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel");
01371       }
01372    }
01373 #endif
01374 
01375 /* From Andreas Dilger e-mail to png-implement, 26 March 1998:
01376  *
01377  *   In most cases, the "simple transparency" should be done prior to doing
01378  *   gray-to-RGB, or you will have to test 3x as many bytes to check if a
01379  *   pixel is transparent.  You would also need to make sure that the
01380  *   transparency information is upgraded to RGB.
01381  *
01382  *   To summarize, the current flow is:
01383  *   - Gray + simple transparency -> compare 1 or 2 gray bytes and composite
01384  *                                   with background "in place" if transparent,
01385  *                                   convert to RGB if necessary
01386  *   - Gray + alpha -> composite with gray background and remove alpha bytes,
01387  *                                   convert to RGB if necessary
01388  *
01389  *   To support RGB backgrounds for gray images we need:
01390  *   - Gray + simple transparency -> convert to RGB + simple transparency,
01391  *                                   compare 3 or 6 bytes and composite with
01392  *                                   background "in place" if transparent
01393  *                                   (3x compare/pixel compared to doing
01394  *                                   composite with gray bkgrnd)
01395  *   - Gray + alpha -> convert to RGB + alpha, composite with background and
01396  *                                   remove alpha bytes (3x float
01397  *                                   operations/pixel compared with composite
01398  *                                   on gray background)
01399  *
01400  *  Greg's change will do this.  The reason it wasn't done before is for
01401  *  performance, as this increases the per-pixel operations.  If we would check
01402  *  in advance if the background was gray or RGB, and position the gray-to-RGB
01403  *  transform appropriately, then it would save a lot of work/time.
01404  */
01405 
01406 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
01407    /* If gray -> RGB, do so now only if background is non-gray; else do later
01408     * for performance reasons
01409     */
01410    if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
01411        !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
01412       png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
01413 #endif
01414 
01415 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
01416    if ((png_ptr->transformations & PNG_BACKGROUND) &&
01417       ((png_ptr->num_trans != 0 ) ||
01418       (png_ptr->color_type & PNG_COLOR_MASK_ALPHA)))
01419       png_do_background(&(png_ptr->row_info), png_ptr->row_buf + 1,
01420          &(png_ptr->trans_values), &(png_ptr->background)
01421 #if defined(PNG_READ_GAMMA_SUPPORTED)
01422          , &(png_ptr->background_1),
01423          png_ptr->gamma_table, png_ptr->gamma_from_1,
01424          png_ptr->gamma_to_1, png_ptr->gamma_16_table,
01425          png_ptr->gamma_16_from_1, png_ptr->gamma_16_to_1,
01426          png_ptr->gamma_shift
01427 #endif
01428 );
01429 #endif
01430 
01431 #if defined(PNG_READ_GAMMA_SUPPORTED)
01432    if ((png_ptr->transformations & PNG_GAMMA) &&
01433 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
01434        !((png_ptr->transformations & PNG_BACKGROUND) &&
01435        ((png_ptr->num_trans != 0) ||
01436        (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) &&
01437 #endif
01438        (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE))
01439       png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1,
01440           png_ptr->gamma_table, png_ptr->gamma_16_table,
01441           png_ptr->gamma_shift);
01442 #endif
01443 
01444 #if defined(PNG_READ_16_TO_8_SUPPORTED)
01445    if (png_ptr->transformations & PNG_16_TO_8)
01446       png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1);
01447 #endif
01448 
01449 #if defined(PNG_READ_DITHER_SUPPORTED)
01450    if (png_ptr->transformations & PNG_DITHER)
01451    {
01452       png_do_dither((png_row_infop)&(png_ptr->row_info), png_ptr->row_buf + 1,
01453          png_ptr->palette_lookup, png_ptr->dither_index);
01454       if (png_ptr->row_info.rowbytes == (png_uint_32)0)
01455          png_error(png_ptr, "png_do_dither returned rowbytes=0");
01456    }
01457 #endif
01458 
01459 #if defined(PNG_READ_INVERT_SUPPORTED)
01460    if (png_ptr->transformations & PNG_INVERT_MONO)
01461       png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1);
01462 #endif
01463 
01464 #if defined(PNG_READ_SHIFT_SUPPORTED)
01465    if (png_ptr->transformations & PNG_SHIFT)
01466       png_do_unshift(&(png_ptr->row_info), png_ptr->row_buf + 1,
01467          &(png_ptr->shift));
01468 #endif
01469 
01470 #if defined(PNG_READ_PACK_SUPPORTED)
01471    if (png_ptr->transformations & PNG_PACK)
01472       png_do_unpack(&(png_ptr->row_info), png_ptr->row_buf + 1);
01473 #endif
01474 
01475 #if defined(PNG_READ_BGR_SUPPORTED)
01476    if (png_ptr->transformations & PNG_BGR)
01477       png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1);
01478 #endif
01479 
01480 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
01481    if (png_ptr->transformations & PNG_PACKSWAP)
01482       png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1);
01483 #endif
01484 
01485 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
01486    /* If gray -> RGB, do so now only if we did not do so above */
01487    if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
01488        (png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
01489       png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
01490 #endif
01491 
01492 #if defined(PNG_READ_FILLER_SUPPORTED)
01493    if (png_ptr->transformations & PNG_FILLER)
01494       png_do_read_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
01495          (png_uint_32)png_ptr->filler, png_ptr->flags);
01496 #endif
01497 
01498 #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
01499    if (png_ptr->transformations & PNG_INVERT_ALPHA)
01500       png_do_read_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
01501 #endif
01502 
01503 #if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
01504    if (png_ptr->transformations & PNG_SWAP_ALPHA)
01505       png_do_read_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
01506 #endif
01507 
01508 #if defined(PNG_READ_SWAP_SUPPORTED)
01509    if (png_ptr->transformations & PNG_SWAP_BYTES)
01510       png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1);
01511 #endif
01512 
01513 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
01514    if (png_ptr->transformations & PNG_USER_TRANSFORM)
01515     {
01516       if (png_ptr->read_user_transform_fn != NULL)
01517          (*(png_ptr->read_user_transform_fn)) /* User read transform function */
01518             (png_ptr,                    /* png_ptr */
01519                &(png_ptr->row_info),     /* row_info: */
01520                /*  png_uint_32 width;       width of row */
01521                /*  png_uint_32 rowbytes;    number of bytes in row */
01522                /*  png_byte color_type;     color type of pixels */
01523                /*  png_byte bit_depth;      bit depth of samples */
01524                /*  png_byte channels;       number of channels (1-4) */
01525                /*  png_byte pixel_depth;    bits per pixel (depth*channels) */
01526                png_ptr->row_buf + 1);    /* start of pixel data for row */
01527 #if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
01528       if (png_ptr->user_transform_depth)
01529          png_ptr->row_info.bit_depth = png_ptr->user_transform_depth;
01530       if (png_ptr->user_transform_channels)
01531          png_ptr->row_info.channels = png_ptr->user_transform_channels;
01532 #endif
01533       png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth *
01534          png_ptr->row_info.channels);
01535       png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth,
01536          png_ptr->row_info.width);
01537    }
01538 #endif
01539 
01540 }
01541 
01542 #if defined(PNG_READ_PACK_SUPPORTED)
01543 /* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel,
01544  * without changing the actual values.  Thus, if you had a row with
01545  * a bit depth of 1, you would end up with bytes that only contained
01546  * the numbers 0 or 1.  If you would rather they contain 0 and 255, use
01547  * png_do_shift() after this.
01548  */
01549 void /* PRIVATE */
01550 png_do_unpack(png_row_infop row_info, png_bytep row)
01551 {
01552    png_debug(1, "in png_do_unpack");
01553 #if defined(PNG_USELESS_TESTS_SUPPORTED)
01554    if (row != NULL && row_info != NULL && row_info->bit_depth < 8)
01555 #else
01556    if (row_info->bit_depth < 8)
01557 #endif
01558    {
01559       png_uint_32 i;
01560       png_uint_32 row_width=row_info->width;
01561 
01562       switch (row_info->bit_depth)
01563       {
01564          case 1:
01565          {
01566             png_bytep sp = row + (png_size_t)((row_width - 1) >> 3);
01567             png_bytep dp = row + (png_size_t)row_width - 1;
01568             png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07);
01569             for (i = 0; i < row_width; i++)
01570             {
01571                *dp = (png_byte)((*sp >> shift) & 0x01);
01572                if (shift == 7)
01573                {
01574                   shift = 0;
01575                   sp--;
01576                }
01577                else
01578                   shift++;
01579 
01580                dp--;
01581             }
01582             break;
01583          }
01584 
01585          case 2:
01586          {
01587 
01588             png_bytep sp = row + (png_size_t)((row_width - 1) >> 2);
01589             png_bytep dp = row + (png_size_t)row_width - 1;
01590             png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
01591             for (i = 0; i < row_width; i++)
01592             {
01593                *dp = (png_byte)((*sp >> shift) & 0x03);
01594                if (shift == 6)
01595                {
01596                   shift = 0;
01597                   sp--;
01598                }
01599                else
01600                   shift += 2;
01601 
01602                dp--;
01603             }
01604             break;
01605          }
01606 
01607          case 4:
01608          {
01609             png_bytep sp = row + (png_size_t)((row_width - 1) >> 1);
01610             png_bytep dp = row + (png_size_t)row_width - 1;
01611             png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
01612             for (i = 0; i < row_width; i++)
01613             {
01614                *dp = (png_byte)((*sp >> shift) & 0x0f);
01615                if (shift == 4)
01616                {
01617                   shift = 0;
01618                   sp--;
01619                }
01620                else
01621                   shift = 4;
01622 
01623                dp--;
01624             }
01625             break;
01626          }
01627       }
01628       row_info->bit_depth = 8;
01629       row_info->pixel_depth = (png_byte)(8 * row_info->channels);
01630       row_info->rowbytes = row_width * row_info->channels;
01631    }
01632 }
01633 #endif
01634 
01635 #if defined(PNG_READ_SHIFT_SUPPORTED)
01636 /* Reverse the effects of png_do_shift.  This routine merely shifts the
01637  * pixels back to their significant bits values.  Thus, if you have
01638  * a row of bit depth 8, but only 5 are significant, this will shift
01639  * the values back to 0 through 31.
01640  */
01641 void /* PRIVATE */
01642 png_do_unshift(png_row_infop row_info, png_bytep row, png_color_8p sig_bits)
01643 {
01644    png_debug(1, "in png_do_unshift");
01645    if (
01646 #if defined(PNG_USELESS_TESTS_SUPPORTED)
01647        row != NULL && row_info != NULL && sig_bits != NULL &&
01648 #endif
01649        row_info->color_type != PNG_COLOR_TYPE_PALETTE)
01650    {
01651       int shift[4];
01652       int channels = 0;
01653       int c;
01654       png_uint_16 value = 0;
01655       png_uint_32 row_width = row_info->width;
01656 
01657       if (row_info->color_type & PNG_COLOR_MASK_COLOR)
01658       {
01659          shift[channels++] = row_info->bit_depth - sig_bits->red;
01660          shift[channels++] = row_info->bit_depth - sig_bits->green;
01661          shift[channels++] = row_info->bit_depth - sig_bits->blue;
01662       }
01663       else
01664       {
01665          shift[channels++] = row_info->bit_depth - sig_bits->gray;
01666       }
01667       if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
01668       {
01669          shift[channels++] = row_info->bit_depth - sig_bits->alpha;
01670       }
01671 
01672       for (c = 0; c < channels; c++)
01673       {
01674          if (shift[c] <= 0)
01675             shift[c] = 0;
01676          else
01677             value = 1;
01678       }
01679 
01680       if (!value)
01681          return;
01682 
01683       switch (row_info->bit_depth)
01684       {
01685          case 2:
01686          {
01687             png_bytep bp;
01688             png_uint_32 i;
01689             png_uint_32 istop = row_info->rowbytes;
01690 
01691             for (bp = row, i = 0; i < istop; i++)
01692             {
01693                *bp >>= 1;
01694                *bp++ &= 0x55;
01695             }
01696             break;
01697          }
01698 
01699          case 4:
01700          {
01701             png_bytep bp = row;
01702             png_uint_32 i;
01703             png_uint_32 istop = row_info->rowbytes;
01704             png_byte mask = (png_byte)((((int)0xf0 >> shift[0]) & (int)0xf0) |
01705                (png_byte)((int)0xf >> shift[0]));
01706 
01707             for (i = 0; i < istop; i++)
01708             {
01709                *bp >>= shift[0];
01710                *bp++ &= mask;
01711             }
01712             break;
01713          }
01714 
01715          case 8:
01716          {
01717             png_bytep bp = row;
01718             png_uint_32 i;
01719             png_uint_32 istop = row_width * channels;
01720 
01721             for (i = 0; i < istop; i++)
01722             {
01723                *bp++ >>= shift[i%channels];
01724             }
01725             break;
01726          }
01727 
01728          case 16:
01729          {
01730             png_bytep bp = row;
01731             png_uint_32 i;
01732             png_uint_32 istop = channels * row_width;
01733 
01734             for (i = 0; i < istop; i++)
01735             {
01736                value = (png_uint_16)((*bp << 8) + *(bp + 1));
01737                value >>= shift[i%channels];
01738                *bp++ = (png_byte)(value >> 8);
01739                *bp++ = (png_byte)(value & 0xff);
01740             }
01741             break;
01742          }
01743       }
01744    }
01745 }
01746 #endif
01747 
01748 #if defined(PNG_READ_16_TO_8_SUPPORTED)
01749 /* Chop rows of bit depth 16 down to 8 */
01750 void /* PRIVATE */
01751 png_do_chop(png_row_infop row_info, png_bytep row)
01752 {
01753    png_debug(1, "in png_do_chop");
01754 #if defined(PNG_USELESS_TESTS_SUPPORTED)
01755    if (row != NULL && row_info != NULL && row_info->bit_depth == 16)
01756 #else
01757    if (row_info->bit_depth == 16)
01758 #endif
01759    {
01760       png_bytep sp = row;
01761       png_bytep dp = row;
01762       png_uint_32 i;
01763       png_uint_32 istop = row_info->width * row_info->channels;
01764 
01765       for (i = 0; i<istop; i++, sp += 2, dp++)
01766       {
01767 #if defined(PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED)
01768       /* This does a more accurate scaling of the 16-bit color
01769        * value, rather than a simple low-byte truncation.
01770        *
01771        * What the ideal calculation should be:
01772        *   *dp = (((((png_uint_32)(*sp) << 8) |
01773        *          (png_uint_32)(*(sp + 1))) * 255 + 127)
01774        *          / (png_uint_32)65535L;
01775        *
01776        * GRR: no, I think this is what it really should be:
01777        *   *dp = (((((png_uint_32)(*sp) << 8) |
01778        *           (png_uint_32)(*(sp + 1))) + 128L)
01779        *           / (png_uint_32)257L;
01780        *
01781        * GRR: here's the exact calculation with shifts:
01782        *   temp = (((png_uint_32)(*sp) << 8) |
01783        *           (png_uint_32)(*(sp + 1))) + 128L;
01784        *   *dp = (temp - (temp >> 8)) >> 8;
01785        *
01786        * Approximate calculation with shift/add instead of multiply/divide:
01787        *   *dp = ((((png_uint_32)(*sp) << 8) |
01788        *          (png_uint_32)((int)(*(sp + 1)) - *sp)) + 128) >> 8;
01789        *
01790        * What we actually do to avoid extra shifting and conversion:
01791        */
01792 
01793          *dp = *sp + ((((int)(*(sp + 1)) - *sp) > 128) ? 1 : 0);
01794 #else
01795        /* Simply discard the low order byte */
01796          *dp = *sp;
01797 #endif
01798       }
01799       row_info->bit_depth = 8;
01800       row_info->pixel_depth = (png_byte)(8 * row_info->channels);
01801       row_info->rowbytes = row_info->width * row_info->channels;
01802    }
01803 }
01804 #endif
01805 
01806 #if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
01807 void /* PRIVATE */
01808 png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
01809 {
01810    png_debug(1, "in png_do_read_swap_alpha");
01811 #if defined(PNG_USELESS_TESTS_SUPPORTED)
01812    if (row != NULL && row_info != NULL)
01813 #endif
01814    {
01815       png_uint_32 row_width = row_info->width;
01816       if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
01817       {
01818          /* This converts from RGBA to ARGB */
01819          if (row_info->bit_depth == 8)
01820          {
01821             png_bytep sp = row + row_info->rowbytes;
01822             png_bytep dp = sp;
01823             png_byte save;
01824             png_uint_32 i;
01825 
01826             for (i = 0; i < row_width; i++)
01827             {
01828                save = *(--sp);
01829                *(--dp) = *(--sp);
01830                *(--dp) = *(--sp);
01831                *(--dp) = *(--sp);
01832                *(--dp) = save;
01833             }
01834          }
01835          /* This converts from RRGGBBAA to AARRGGBB */
01836          else
01837          {
01838             png_bytep sp = row + row_info->rowbytes;
01839             png_bytep dp = sp;
01840             png_byte save[2];
01841             png_uint_32 i;
01842 
01843             for (i = 0; i < row_width; i++)
01844             {
01845                save[0] = *(--sp);
01846                save[1] = *(--sp);
01847                *(--dp) = *(--sp);
01848                *(--dp) = *(--sp);
01849                *(--dp) = *(--sp);
01850                *(--dp) = *(--sp);
01851                *(--dp) = *(--sp);
01852                *(--dp) = *(--sp);
01853                *(--dp) = save[0];
01854                *(--dp) = save[1];
01855             }
01856          }
01857       }
01858       else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
01859       {
01860          /* This converts from GA to AG */
01861          if (row_info->bit_depth == 8)
01862          {
01863             png_bytep sp = row + row_info->rowbytes;
01864             png_bytep dp = sp;
01865             png_byte save;
01866             png_uint_32 i;
01867 
01868             for (i = 0; i < row_width; i++)
01869             {
01870                save = *(--sp);
01871                *(--dp) = *(--sp);
01872                *(--dp) = save;
01873             }
01874          }
01875          /* This converts from GGAA to AAGG */
01876          else
01877          {
01878             png_bytep sp = row + row_info->rowbytes;
01879             png_bytep dp = sp;
01880             png_byte save[2];
01881             png_uint_32 i;
01882 
01883             for (i = 0; i < row_width; i++)
01884             {
01885                save[0] = *(--sp);
01886                save[1] = *(--sp);
01887                *(--dp) = *(--sp);
01888                *(--dp) = *(--sp);
01889                *(--dp) = save[0];
01890                *(--dp) = save[1];
01891             }
01892          }
01893       }
01894    }
01895 }
01896 #endif
01897 
01898 #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
01899 void /* PRIVATE */
01900 png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
01901 {
01902    png_debug(1, "in png_do_read_invert_alpha");
01903 #if defined(PNG_USELESS_TESTS_SUPPORTED)
01904    if (row != NULL && row_info != NULL)
01905 #endif
01906    {
01907       png_uint_32 row_width = row_info->width;
01908       if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
01909       {
01910          /* This inverts the alpha channel in RGBA */
01911          if (row_info->bit_depth == 8)
01912          {
01913             png_bytep sp = row + row_info->rowbytes;
01914             png_bytep dp = sp;
01915             png_uint_32 i;
01916 
01917             for (i = 0; i < row_width; i++)
01918             {
01919                *(--dp) = (png_byte)(255 - *(--sp));
01920 
01921 /*             This does nothing:
01922                *(--dp) = *(--sp);
01923                *(--dp) = *(--sp);
01924                *(--dp) = *(--sp);
01925                We can replace it with:
01926 */
01927                sp-=3;
01928                dp=sp;
01929             }
01930          }
01931          /* This inverts the alpha channel in RRGGBBAA */
01932          else
01933          {
01934             png_bytep sp = row + row_info->rowbytes;
01935             png_bytep dp = sp;
01936             png_uint_32 i;
01937 
01938             for (i = 0; i < row_width; i++)
01939             {
01940                *(--dp) = (png_byte)(255 - *(--sp));
01941                *(--dp) = (png_byte)(255 - *(--sp));
01942 
01943 /*             This does nothing:
01944                *(--dp) = *(--sp);
01945                *(--dp) = *(--sp);
01946                *(--dp) = *(--sp);
01947                *(--dp) = *(--sp);
01948                *(--dp) = *(--sp);
01949                *(--dp) = *(--sp);
01950                We can replace it with:
01951 */
01952                sp-=6;
01953                dp=sp;
01954             }
01955          }
01956       }
01957       else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
01958       {
01959          /* This inverts the alpha channel in GA */
01960          if (row_info->bit_depth == 8)
01961          {
01962             png_bytep sp = row + row_info->rowbytes;
01963             png_bytep dp = sp;
01964             png_uint_32 i;
01965 
01966             for (i = 0; i < row_width; i++)
01967             {
01968                *(--dp) = (png_byte)(255 - *(--sp));
01969                *(--dp) = *(--sp);
01970             }
01971          }
01972          /* This inverts the alpha channel in GGAA */
01973          else
01974          {
01975             png_bytep sp  = row + row_info->rowbytes;
01976             png_bytep dp = sp;
01977             png_uint_32 i;
01978 
01979             for (i = 0; i < row_width; i++)
01980             {
01981                *(--dp) = (png_byte)(255 - *(--sp));
01982                *(--dp) = (png_byte)(255 - *(--sp));
01983 /*
01984                *(--dp) = *(--sp);
01985                *(--dp) = *(--sp);
01986 */
01987                sp-=2;
01988                dp=sp;
01989             }
01990          }
01991       }
01992    }
01993 }
01994 #endif
01995 
01996 #if defined(PNG_READ_FILLER_SUPPORTED)
01997 /* Add filler channel if we have RGB color */
01998 void /* PRIVATE */
01999 png_do_read_filler(png_row_infop row_info, png_bytep row,
02000    png_uint_32 filler, png_uint_32 flags)
02001 {
02002    png_uint_32 i;
02003    png_uint_32 row_width = row_info->width;
02004 
02005    png_byte hi_filler = (png_byte)((filler>>8) & 0xff);
02006    png_byte lo_filler = (png_byte)(filler & 0xff);
02007 
02008    png_debug(1, "in png_do_read_filler");
02009    if (
02010 #if defined(PNG_USELESS_TESTS_SUPPORTED)
02011        row != NULL  && row_info != NULL &&
02012 #endif
02013        row_info->color_type == PNG_COLOR_TYPE_GRAY)
02014    {
02015       if (row_info->bit_depth == 8)
02016       {
02017          /* This changes the data from G to GX */
02018          if (flags & PNG_FLAG_FILLER_AFTER)
02019          {
02020             png_bytep sp = row + (png_size_t)row_width;
02021             png_bytep dp =  sp + (png_size_t)row_width;
02022             for (i = 1; i < row_width; i++)
02023             {
02024                *(--dp) = lo_filler;
02025                *(--dp) = *(--sp);
02026             }
02027             *(--dp) = lo_filler;
02028             row_info->channels = 2;
02029             row_info->pixel_depth = 16;
02030             row_info->rowbytes = row_width * 2;
02031          }
02032       /* This changes the data from G to XG */
02033          else
02034          {
02035             png_bytep sp = row + (png_size_t)row_width;
02036             png_bytep dp = sp  + (png_size_t)row_width;
02037             for (i = 0; i < row_width; i++)
02038             {
02039                *(--dp) = *(--sp);
02040                *(--dp) = lo_filler;
02041             }
02042             row_info->channels = 2;
02043             row_info->pixel_depth = 16;
02044             row_info->rowbytes = row_width * 2;
02045          }
02046       }
02047       else if (row_info->bit_depth == 16)
02048       {
02049          /* This changes the data from GG to GGXX */
02050          if (flags & PNG_FLAG_FILLER_AFTER)
02051          {
02052             png_bytep sp = row + (png_size_t)row_width * 2;
02053             png_bytep dp = sp  + (png_size_t)row_width * 2;
02054             for (i = 1; i < row_width; i++)
02055             {
02056                *(--dp) = hi_filler;
02057                *(--dp) = lo_filler;
02058                *(--dp) = *(--sp);
02059                *(--dp) = *(--sp);
02060             }
02061             *(--dp) = hi_filler;
02062             *(--dp) = lo_filler;
02063             row_info->channels = 2;
02064             row_info->pixel_depth = 32;
02065             row_info->rowbytes = row_width * 4;
02066          }
02067          /* This changes the data from GG to XXGG */
02068          else
02069          {
02070             png_bytep sp = row + (png_size_t)row_width * 2;
02071             png_bytep dp = sp  + (png_size_t)row_width * 2;
02072             for (i = 0; i < row_width; i++)
02073             {
02074                *(--dp) = *(--sp);
02075                *(--dp) = *(--sp);
02076                *(--dp) = hi_filler;
02077                *(--dp) = lo_filler;
02078             }
02079             row_info->channels = 2;
02080             row_info->pixel_depth = 32;
02081             row_info->rowbytes = row_width * 4;
02082          }
02083       }
02084    } /* COLOR_TYPE == GRAY */
02085    else if (row_info->color_type == PNG_COLOR_TYPE_RGB)
02086    {
02087       if (row_info->bit_depth == 8)
02088       {
02089          /* This changes the data from RGB to RGBX */
02090          if (flags & PNG_FLAG_FILLER_AFTER)
02091          {
02092             png_bytep sp = row + (png_size_t)row_width * 3;
02093             png_bytep dp = sp  + (png_size_t)row_width;
02094             for (i = 1; i < row_width; i++)
02095             {
02096                *(--dp) = lo_filler;
02097                *(--dp) = *(--sp);
02098                *(--dp) = *(--sp);
02099                *(--dp) = *(--sp);
02100             }
02101             *(--dp) = lo_filler;
02102             row_info->channels = 4;
02103             row_info->pixel_depth = 32;
02104             row_info->rowbytes = row_width * 4;
02105          }
02106       /* This changes the data from RGB to XRGB */
02107          else
02108          {
02109             png_bytep sp = row + (png_size_t)row_width * 3;
02110             png_bytep dp = sp + (png_size_t)row_width;
02111             for (i = 0; i < row_width; i++)
02112             {
02113                *(--dp) = *(--sp);
02114                *(--dp) = *(--sp);
02115                *(--dp) = *(--sp);
02116                *(--dp) = lo_filler;
02117             }
02118             row_info->channels = 4;
02119             row_info->pixel_depth = 32;
02120             row_info->rowbytes = row_width * 4;
02121          }
02122       }
02123       else if (row_info->bit_depth == 16)
02124       {
02125          /* This changes the data from RRGGBB to RRGGBBXX */
02126          if (flags & PNG_FLAG_FILLER_AFTER)
02127          {
02128             png_bytep sp = row + (png_size_t)row_width * 6;
02129             png_bytep dp = sp  + (png_size_t)row_width * 2;
02130             for (i = 1; i < row_width; i++)
02131             {
02132                *(--dp) = hi_filler;
02133                *(--dp) = lo_filler;
02134                *(--dp) = *(--sp);
02135                *(--dp) = *(--sp);
02136                *(--dp) = *(--sp);
02137                *(--dp) = *(--sp);
02138                *(--dp) = *(--sp);
02139                *(--dp) = *(--sp);
02140             }
02141             *(--dp) = hi_filler;
02142             *(--dp) = lo_filler;
02143             row_info->channels = 4;
02144             row_info->pixel_depth = 64;
02145             row_info->rowbytes = row_width * 8;
02146          }
02147          /* This changes the data from RRGGBB to XXRRGGBB */
02148          else
02149          {
02150             png_bytep sp = row + (png_size_t)row_width * 6;
02151             png_bytep dp = sp  + (png_size_t)row_width * 2;
02152             for (i = 0; i < row_width; i++)
02153             {
02154                *(--dp) = *(--sp);
02155                *(--dp) = *(--sp);
02156                *(--dp) = *(--sp);
02157                *(--dp) = *(--sp);
02158                *(--dp) = *(--sp);
02159                *(--dp) = *(--sp);
02160                *(--dp) = hi_filler;
02161                *(--dp) = lo_filler;
02162             }
02163             row_info->channels = 4;
02164             row_info->pixel_depth = 64;
02165             row_info->rowbytes = row_width * 8;
02166          }
02167       }
02168    } /* COLOR_TYPE == RGB */
02169 }
02170 #endif
02171 
02172 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
02173 /* Expand grayscale files to RGB, with or without alpha */
02174 void /* PRIVATE */
02175 png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
02176 {
02177    png_uint_32 i;
02178    png_uint_32 row_width = row_info->width;
02179 
02180    png_debug(1, "in png_do_gray_to_rgb");
02181    if (row_info->bit_depth >= 8 &&
02182 #if defined(PNG_USELESS_TESTS_SUPPORTED)
02183        row != NULL && row_info != NULL &&
02184 #endif
02185       !(row_info->color_type & PNG_COLOR_MASK_COLOR))
02186    {
02187       if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
02188       {
02189          if (row_info->bit_depth == 8)
02190          {
02191             png_bytep sp = row + (png_size_t)row_width - 1;
02192             png_bytep dp = sp  + (png_size_t)row_width * 2;
02193             for (i = 0; i < row_width; i++)
02194             {
02195                *(dp--) = *sp;
02196                *(dp--) = *sp;
02197                *(dp--) = *(sp--);
02198             }
02199          }
02200          else
02201          {
02202             png_bytep sp = row + (png_size_t)row_width * 2 - 1;
02203             png_bytep dp = sp  + (png_size_t)row_width * 4;
02204             for (i = 0; i < row_width; i++)
02205             {
02206                *(dp--) = *sp;
02207                *(dp--) = *(sp - 1);
02208                *(dp--) = *sp;
02209                *(dp--) = *(sp - 1);
02210                *(dp--) = *(sp--);
02211                *(dp--) = *(sp--);
02212             }
02213          }
02214       }
02215       else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
02216       {
02217          if (row_info->bit_depth == 8)
02218          {
02219             png_bytep sp = row + (png_size_t)row_width * 2 - 1;
02220             png_bytep dp = sp  + (png_size_t)row_width * 2;
02221             for (i = 0; i < row_width; i++)
02222             {
02223                *(dp--) = *(sp--);
02224                *(dp--) = *sp;
02225                *(dp--) = *sp;
02226                *(dp--) = *(sp--);
02227             }
02228          }
02229          else
02230          {
02231             png_bytep sp = row + (png_size_t)row_width * 4 - 1;
02232             png_bytep dp = sp  + (png_size_t)row_width * 4;
02233             for (i = 0; i < row_width; i++)
02234             {
02235                *(dp--) = *(sp--);
02236                *(dp--) = *(sp--);
02237                *(dp--) = *sp;
02238                *(dp--) = *(sp - 1);
02239                *(dp--) = *sp;
02240                *(dp--) = *(sp - 1);
02241                *(dp--) = *(sp--);
02242                *(dp--) = *(sp--);
02243             }
02244          }
02245       }
02246       row_info->channels += (png_byte)2;
02247       row_info->color_type |= PNG_COLOR_MASK_COLOR;
02248       row_info->pixel_depth = (png_byte)(row_info->channels *
02249          row_info->bit_depth);
02250       row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
02251    }
02252 }
02253 #endif
02254 
02255 #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
02256 /* Reduce RGB files to grayscale, with or without alpha
02257  * using the equation given in Poynton's ColorFAQ at
02258  * <http://www.inforamp.net/~poynton/>  (THIS LINK IS DEAD June 2008)
02259  * New link:
02260  * <http://www.poynton.com/notes/colour_and_gamma/>
02261  * Charles Poynton poynton at poynton.com
02262  *
02263  *     Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
02264  *
02265  *  We approximate this with
02266  *
02267  *     Y = 0.21268 * R    + 0.7151 * G    + 0.07217 * B
02268  *
02269  *  which can be expressed with integers as
02270  *
02271  *     Y = (6969 * R + 23434 * G + 2365 * B)/32768
02272  *
02273  *  The calculation is to be done in a linear colorspace.
02274  *
02275  *  Other integer coefficents can be used via png_set_rgb_to_gray().
02276  */
02277 int /* PRIVATE */
02278 png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
02279 
02280 {
02281    png_uint_32 i;
02282 
02283    png_uint_32 row_width = row_info->width;
02284    int rgb_error = 0;
02285 
02286    png_debug(1, "in png_do_rgb_to_gray");
02287    if (
02288 #if defined(PNG_USELESS_TESTS_SUPPORTED)
02289        row != NULL && row_info != NULL &&
02290 #endif
02291       (row_info->color_type & PNG_COLOR_MASK_COLOR))
02292    {
02293       png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff;
02294       png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff;
02295       png_uint_32 bc = png_ptr->rgb_to_gray_blue_coeff;
02296 
02297       if (row_info->color_type == PNG_COLOR_TYPE_RGB)
02298       {
02299          if (row_info->bit_depth == 8)
02300          {
02301 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
02302             if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
02303             {
02304                png_bytep sp = row;
02305                png_bytep dp = row;
02306 
02307                for (i = 0; i < row_width; i++)
02308                {
02309                   png_byte red   = png_ptr->gamma_to_1[*(sp++)];
02310                   png_byte green = png_ptr->gamma_to_1[*(sp++)];
02311                   png_byte blue  = png_ptr->gamma_to_1[*(sp++)];
02312                   if (red != green || red != blue)
02313                   {
02314                      rgb_error |= 1;
02315                      *(dp++) = png_ptr->gamma_from_1[
02316                        (rc*red + gc*green + bc*blue)>>15];
02317                   }
02318                   else
02319                      *(dp++) = *(sp - 1);
02320                }
02321             }
02322             else
02323 #endif
02324             {
02325                png_bytep sp = row;
02326                png_bytep dp = row;
02327                for (i = 0; i < row_width; i++)
02328                {
02329                   png_byte red   = *(sp++);
02330                   png_byte green = *(sp++);
02331                   png_byte blue  = *(sp++);
02332                   if (red != green || red != blue)
02333                   {
02334                      rgb_error |= 1;
02335                      *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15);
02336                   }
02337                   else
02338                      *(dp++) = *(sp - 1);
02339                }
02340             }
02341          }
02342 
02343          else /* RGB bit_depth == 16 */
02344          {
02345 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
02346             if (png_ptr->gamma_16_to_1 != NULL &&
02347                 png_ptr->gamma_16_from_1 != NULL)
02348             {
02349                png_bytep sp = row;
02350                png_bytep dp = row;
02351                for (i = 0; i < row_width; i++)
02352                {
02353                   png_uint_16 red, green, blue, w;
02354 
02355                   red   = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
02356                   green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
02357                   blue  = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
02358 
02359                   if (red == green && red == blue)
02360                      w = red;
02361                   else
02362                   {
02363                      png_uint_16 red_1   = png_ptr->gamma_16_to_1[(red&0xff) >>
02364                                   png_ptr->gamma_shift][red>>8];
02365                      png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >>
02366                                   png_ptr->gamma_shift][green>>8];
02367                      png_uint_16 blue_1  = png_ptr->gamma_16_to_1[(blue&0xff) >>
02368                                   png_ptr->gamma_shift][blue>>8];
02369                      png_uint_16 gray16  = (png_uint_16)((rc*red_1 + gc*green_1
02370                                   + bc*blue_1)>>15);
02371                      w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
02372                          png_ptr->gamma_shift][gray16 >> 8];
02373                      rgb_error |= 1;
02374                   }
02375 
02376                   *(dp++) = (png_byte)((w>>8) & 0xff);
02377                   *(dp++) = (png_byte)(w & 0xff);
02378                }
02379             }
02380             else
02381 #endif
02382             {
02383                png_bytep sp = row;
02384                png_bytep dp = row;
02385                for (i = 0; i < row_width; i++)
02386                {
02387                   png_uint_16 red, green, blue, gray16;
02388 
02389                   red   = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
02390                   green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
02391                   blue  = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
02392 
02393                   if (red != green || red != blue)
02394                      rgb_error |= 1;
02395                   gray16  = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
02396                   *(dp++) = (png_byte)((gray16>>8) & 0xff);
02397                   *(dp++) = (png_byte)(gray16 & 0xff);
02398                }
02399             }
02400          }
02401       }
02402       if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
02403       {
02404          if (row_info->bit_depth == 8)
02405          {
02406 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
02407             if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
02408             {
02409                png_bytep sp = row;
02410                png_bytep dp = row;
02411                for (i = 0; i < row_width; i++)
02412                {
02413                   png_byte red   = png_ptr->gamma_to_1[*(sp++)];
02414                   png_byte green = png_ptr->gamma_to_1[*(sp++)];
02415                   png_byte blue  = png_ptr->gamma_to_1[*(sp++)];
02416                   if (red != green || red != blue)
02417                      rgb_error |= 1;
02418                   *(dp++) =  png_ptr->gamma_from_1
02419                              [(rc*red + gc*green + bc*blue)>>15];
02420                   *(dp++) = *(sp++);  /* alpha */
02421                }
02422             }
02423             else
02424 #endif
02425             {
02426                png_bytep sp = row;
02427                png_bytep dp = row;
02428                for (i = 0; i < row_width; i++)
02429                {
02430                   png_byte red   = *(sp++);
02431                   png_byte green = *(sp++);
02432                   png_byte blue  = *(sp++);
02433                   if (red != green || red != blue)
02434                      rgb_error |= 1;
02435                   *(dp++) =  (png_byte)((rc*red + gc*green + bc*blue)>>15);
02436                   *(dp++) = *(sp++);  /* alpha */
02437                }
02438             }
02439          }
02440          else /* RGBA bit_depth == 16 */
02441          {
02442 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
02443             if (png_ptr->gamma_16_to_1 != NULL &&
02444                 png_ptr->gamma_16_from_1 != NULL)
02445             {
02446                png_bytep sp = row;
02447                png_bytep dp = row;
02448                for (i = 0; i < row_width; i++)
02449                {
02450                   png_uint_16 red, green, blue, w;
02451 
02452                   red   = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
02453                   green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
02454                   blue  = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
02455 
02456                   if (red == green && red == blue)
02457                      w = red;
02458                   else
02459                   {
02460                      png_uint_16 red_1   = png_ptr->gamma_16_to_1[(red&0xff) >>
02461                                   png_ptr->gamma_shift][red>>8];
02462                      png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >>
02463                                   png_ptr->gamma_shift][green>>8];
02464                      png_uint_16 blue_1  = png_ptr->gamma_16_to_1[(blue&0xff) >>
02465                                   png_ptr->gamma_shift][blue>>8];
02466                      png_uint_16 gray16  = (png_uint_16)((rc * red_1
02467                                   + gc * green_1 + bc * blue_1)>>15);
02468                      w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
02469                          png_ptr->gamma_shift][gray16 >> 8];
02470                      rgb_error |= 1;
02471                   }
02472 
02473                   *(dp++) = (png_byte)((w>>8) & 0xff);
02474                   *(dp++) = (png_byte)(w & 0xff);
02475                   *(dp++) = *(sp++);  /* alpha */
02476                   *(dp++) = *(sp++);
02477                }
02478             }
02479             else
02480 #endif
02481             {
02482                png_bytep sp = row;
02483                png_bytep dp = row;
02484                for (i = 0; i < row_width; i++)
02485                {
02486                   png_uint_16 red, green, blue, gray16;
02487                   red   = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
02488                   green = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
02489                   blue  = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
02490                   if (red != green || red != blue)
02491                      rgb_error |= 1;
02492                   gray16  = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
02493                   *(dp++) = (png_byte)((gray16>>8) & 0xff);
02494                   *(dp++) = (png_byte)(gray16 & 0xff);
02495                   *(dp++) = *(sp++);  /* alpha */
02496                   *(dp++) = *(sp++);
02497                }
02498             }
02499          }
02500       }
02501    row_info->channels -= (png_byte)2;
02502       row_info->color_type &= ~PNG_COLOR_MASK_COLOR;
02503       row_info->pixel_depth = (png_byte)(row_info->channels *
02504          row_info->bit_depth);
02505       row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
02506    }
02507    return rgb_error;
02508 }
02509 #endif
02510 
02511 /* Build a grayscale palette.  Palette is assumed to be 1 << bit_depth
02512  * large of png_color.  This lets grayscale images be treated as
02513  * paletted.  Most useful for gamma correction and simplification
02514  * of code.
02515  */
02516 void PNGAPI
02517 png_build_grayscale_palette(int bit_depth, png_colorp palette)
02518 {
02519    int num_palette;
02520    int color_inc;
02521    int i;
02522    int v;
02523 
02524    png_debug(1, "in png_do_build_grayscale_palette");
02525    if (palette == NULL)
02526       return;
02527 
02528    switch (bit_depth)
02529    {
02530       case 1:
02531          num_palette = 2;
02532          color_inc = 0xff;
02533          break;
02534 
02535       case 2:
02536          num_palette = 4;
02537          color_inc = 0x55;
02538          break;
02539 
02540       case 4:
02541          num_palette = 16;
02542          color_inc = 0x11;
02543          break;
02544 
02545       case 8:
02546          num_palette = 256;
02547          color_inc = 1;
02548          break;
02549 
02550       default:
02551          num_palette = 0;
02552          color_inc = 0;
02553          break;
02554    }
02555 
02556    for (i = 0, v = 0; i < num_palette; i++, v += color_inc)
02557    {
02558       palette[i].red = (png_byte)v;
02559       palette[i].green = (png_byte)v;
02560       palette[i].blue = (png_byte)v;
02561    }
02562 }
02563 
02564 /* This function is currently unused.  Do we really need it? */
02565 #if defined(PNG_READ_DITHER_SUPPORTED) && defined(PNG_CORRECT_PALETTE_SUPPORTED)
02566 void /* PRIVATE */
02567 png_correct_palette(png_structp png_ptr, png_colorp palette,
02568    int num_palette)
02569 {
02570    png_debug(1, "in png_correct_palette");
02571 #if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
02572     defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
02573    if (png_ptr->transformations & (PNG_GAMMA | PNG_BACKGROUND))
02574    {
02575       png_color back, back_1;
02576 
02577       if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
02578       {
02579          back.red = png_ptr->gamma_table[png_ptr->background.red];
02580          back.green = png_ptr->gamma_table[png_ptr->background.green];
02581          back.blue = png_ptr->gamma_table[png_ptr->background.blue];
02582 
02583          back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
02584          back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
02585          back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
02586       }
02587       else
02588       {
02589          double g;
02590 
02591          g = 1.0 / (png_ptr->background_gamma * png_ptr->screen_gamma);
02592 
02593          if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_SCREEN ||
02594              fabs(g - 1.0) < PNG_GAMMA_THRESHOLD)
02595          {
02596             back.red = png_ptr->background.red;
02597             back.green = png_ptr->background.green;
02598             back.blue = png_ptr->background.blue;
02599          }
02600          else
02601          {
02602             back.red =
02603                (png_byte)(pow((double)png_ptr->background.red/255, g) *
02604                 255.0 + 0.5);
02605             back.green =
02606                (png_byte)(pow((double)png_ptr->background.green/255, g) *
02607                 255.0 + 0.5);
02608             back.blue =
02609                (png_byte)(pow((double)png_ptr->background.blue/255, g) *
02610                 255.0 + 0.5);
02611          }
02612 
02613          g = 1.0 / png_ptr->background_gamma;
02614 
02615          back_1.red =
02616             (png_byte)(pow((double)png_ptr->background.red/255, g) *
02617              255.0 + 0.5);
02618          back_1.green =
02619             (png_byte)(pow((double)png_ptr->background.green/255, g) *
02620              255.0 + 0.5);
02621          back_1.blue =
02622             (png_byte)(pow((double)png_ptr->background.blue/255, g) *
02623              255.0 + 0.5);
02624       }
02625 
02626       if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
02627       {
02628          png_uint_32 i;
02629 
02630          for (i = 0; i < (png_uint_32)num_palette; i++)
02631          {
02632             if (i < png_ptr->num_trans && png_ptr->trans[i] == 0)
02633             {
02634                palette[i] = back;
02635             }
02636             else if (i < png_ptr->num_trans && png_ptr->trans[i] != 0xff)
02637             {
02638                png_byte v, w;
02639 
02640                v = png_ptr->gamma_to_1[png_ptr->palette[i].red];
02641                png_composite(w, v, png_ptr->trans[i], back_1.red);
02642                palette[i].red = png_ptr->gamma_from_1[w];
02643 
02644                v = png_ptr->gamma_to_1[png_ptr->palette[i].green];
02645                png_composite(w, v, png_ptr->trans[i], back_1.green);
02646                palette[i].green = png_ptr->gamma_from_1[w];
02647 
02648                v = png_ptr->gamma_to_1[png_ptr->palette[i].blue];
02649                png_composite(w, v, png_ptr->trans[i], back_1.blue);
02650                palette[i].blue = png_ptr->gamma_from_1[w];
02651             }
02652             else
02653             {
02654                palette[i].red = png_ptr->gamma_table[palette[i].red];
02655                palette[i].green = png_ptr->gamma_table[palette[i].green];
02656                palette[i].blue = png_ptr->gamma_table[palette[i].blue];
02657             }
02658          }
02659       }
02660       else
02661       {
02662          int i;
02663 
02664          for (i = 0; i < num_palette; i++)
02665          {
02666             if (palette[i].red == (png_byte)png_ptr->trans_values.gray)
02667             {
02668                palette[i] = back;
02669             }
02670             else
02671             {
02672                palette[i].red = png_ptr->gamma_table[palette[i].red];
02673                palette[i].green = png_ptr->gamma_table[palette[i].green];
02674                palette[i].blue = png_ptr->gamma_table[palette[i].blue];
02675             }
02676          }
02677       }
02678    }
02679    else
02680 #endif
02681 #if defined(PNG_READ_GAMMA_SUPPORTED)
02682    if (png_ptr->transformations & PNG_GAMMA)
02683    {
02684       int i;
02685 
02686       for (i = 0; i < num_palette; i++)
02687       {
02688          palette[i].red = png_ptr->gamma_table[palette[i].red];
02689          palette[i].green = png_ptr->gamma_table[palette[i].green];
02690          palette[i].blue = png_ptr->gamma_table[palette[i].blue];
02691       }
02692    }
02693 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
02694    else
02695 #endif
02696 #endif
02697 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
02698    if (png_ptr->transformations & PNG_BACKGROUND)
02699    {
02700       if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
02701       {
02702          png_color back;
02703 
02704          back.red   = (png_byte)png_ptr->background.red;
02705          back.green = (png_byte)png_ptr->background.green;
02706          back.blue  = (png_byte)png_ptr->background.blue;
02707 
02708          for (i = 0; i < (int)png_ptr->num_trans; i++)
02709          {
02710             if (png_ptr->trans[i] == 0)
02711             {
02712                palette[i].red = back.red;
02713                palette[i].green = back.green;
02714                palette[i].blue = back.blue;
02715             }
02716             else if (png_ptr->trans[i] != 0xff)
02717             {
02718                png_composite(palette[i].red, png_ptr->palette[i].red,
02719                   png_ptr->trans[i], back.red);
02720                png_composite(palette[i].green, png_ptr->palette[i].green,
02721                   png_ptr->trans[i], back.green);
02722                png_composite(palette[i].blue, png_ptr->palette[i].blue,
02723                   png_ptr->trans[i], back.blue);
02724             }
02725          }
02726       }
02727       else /* Assume grayscale palette (what else could it be?) */
02728       {
02729          int i;
02730 
02731          for (i = 0; i < num_palette; i++)
02732          {
02733             if (i == (png_byte)png_ptr->trans_values.gray)
02734             {
02735                palette[i].red = (png_byte)png_ptr->background.red;
02736                palette[i].green = (png_byte)png_ptr->background.green;
02737                palette[i].blue = (png_byte)png_ptr->background.blue;
02738             }
02739          }
02740       }
02741    }
02742 #endif
02743 }
02744 #endif
02745 
02746 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
02747 /* Replace any alpha or transparency with the supplied background color.
02748  * "background" is already in the screen gamma, while "background_1" is
02749  * at a gamma of 1.0.  Paletted files have already been taken care of.
02750  */
02751 void /* PRIVATE */
02752 png_do_background(png_row_infop row_info, png_bytep row,
02753    png_color_16p trans_values, png_color_16p background
02754 #if defined(PNG_READ_GAMMA_SUPPORTED)
02755    , png_color_16p background_1,
02756    png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1,
02757    png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1,
02758    png_uint_16pp gamma_16_to_1, int gamma_shift
02759 #endif
02760    )
02761 {
02762    png_bytep sp, dp;
02763    png_uint_32 i;
02764    png_uint_32 row_width=row_info->width;
02765    int shift;
02766 
02767    png_debug(1, "in png_do_background");
02768    if (background != NULL &&
02769 #if defined(PNG_USELESS_TESTS_SUPPORTED)
02770        row != NULL && row_info != NULL &&
02771 #endif
02772       (!(row_info->color_type & PNG_COLOR_MASK_ALPHA) ||
02773       (row_info->color_type != PNG_COLOR_TYPE_PALETTE && trans_values)))
02774    {
02775       switch (row_info->color_type)
02776       {
02777          case PNG_COLOR_TYPE_GRAY:
02778          {
02779             switch (row_info->bit_depth)
02780             {
02781                case 1:
02782                {
02783                   sp = row;
02784                   shift = 7;
02785                   for (i = 0; i < row_width; i++)
02786                   {
02787                      if ((png_uint_16)((*sp >> shift) & 0x01)
02788                         == trans_values->gray)
02789                      {
02790                         *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
02791                         *sp |= (png_byte)(background->gray << shift);
02792                      }
02793                      if (!shift)
02794                      {
02795                         shift = 7;
02796                         sp++;
02797                      }
02798                      else
02799                         shift--;
02800                   }
02801                   break;
02802                }
02803 
02804                case 2:
02805                {
02806 #if defined(PNG_READ_GAMMA_SUPPORTED)
02807                   if (gamma_table != NULL)
02808                   {
02809                      sp = row;
02810                      shift = 6;
02811                      for (i = 0; i < row_width; i++)
02812                      {
02813                         if ((png_uint_16)((*sp >> shift) & 0x03)
02814                             == trans_values->gray)
02815                         {
02816                            *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
02817                            *sp |= (png_byte)(background->gray << shift);
02818                         }
02819                         else
02820                         {
02821                            png_byte p = (png_byte)((*sp >> shift) & 0x03);
02822                            png_byte g = (png_byte)((gamma_table [p | (p << 2) |
02823                                (p << 4) | (p << 6)] >> 6) & 0x03);
02824                            *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
02825                            *sp |= (png_byte)(g << shift);
02826                         }
02827                         if (!shift)
02828                         {
02829                            shift = 6;
02830                            sp++;
02831                         }
02832                         else
02833                            shift -= 2;
02834                      }
02835                   }
02836                   else
02837 #endif
02838                   {
02839                      sp = row;
02840                      shift = 6;
02841                      for (i = 0; i < row_width; i++)
02842                      {
02843                         if ((png_uint_16)((*sp >> shift) & 0x03)
02844                             == trans_values->gray)
02845                         {
02846                            *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
02847                            *sp |= (png_byte)(background->gray << shift);
02848                         }
02849                         if (!shift)
02850                         {
02851                            shift = 6;
02852                            sp++;
02853                         }
02854                         else
02855                            shift -= 2;
02856                      }
02857                   }
02858                   break;
02859                }
02860 
02861                case 4:
02862                {
02863 #if defined(PNG_READ_GAMMA_SUPPORTED)
02864                   if (gamma_table != NULL)
02865                   {
02866                      sp = row;
02867                      shift = 4;
02868                      for (i = 0; i < row_width; i++)
02869                      {
02870                         if ((png_uint_16)((*sp >> shift) & 0x0f)
02871                             == trans_values->gray)
02872                         {
02873                            *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
02874                            *sp |= (png_byte)(background->gray << shift);
02875                         }
02876                         else
02877                         {
02878                            png_byte p = (png_byte)((*sp >> shift) & 0x0f);
02879                            png_byte g = (png_byte)((gamma_table[p |
02880                              (p << 4)] >> 4) & 0x0f);
02881                            *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
02882                            *sp |= (png_byte)(g << shift);
02883                         }
02884                         if (!shift)
02885                         {
02886                            shift = 4;
02887                            sp++;
02888                         }
02889                         else
02890                            shift -= 4;
02891                      }
02892                   }
02893                   else
02894 #endif
02895                   {
02896                      sp = row;
02897                      shift = 4;
02898                      for (i = 0; i < row_width; i++)
02899                      {
02900                         if ((png_uint_16)((*sp >> shift) & 0x0f)
02901                             == trans_values->gray)
02902                         {
02903                            *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
02904                            *sp |= (png_byte)(background->gray << shift);
02905                         }
02906                         if (!shift)
02907                         {
02908                            shift = 4;
02909                            sp++;
02910                         }
02911                         else
02912                            shift -= 4;
02913                      }
02914                   }
02915                   break;
02916                }
02917 
02918                case 8:
02919                {
02920 #if defined(PNG_READ_GAMMA_SUPPORTED)
02921                   if (gamma_table != NULL)
02922                   {
02923                      sp = row;
02924                      for (i = 0; i < row_width; i++, sp++)
02925                      {
02926                         if (*sp == trans_values->gray)
02927                         {
02928                            *sp = (png_byte)background->gray;
02929                         }
02930                         else
02931                         {
02932                            *sp = gamma_table[*sp];
02933                         }
02934                      }
02935                   }
02936                   else
02937 #endif
02938                   {
02939                      sp = row;
02940                      for (i = 0; i < row_width; i++, sp++)
02941                      {
02942                         if (*sp == trans_values->gray)
02943                         {
02944                            *sp = (png_byte)background->gray;
02945                         }
02946                      }
02947                   }
02948                   break;
02949                }
02950 
02951                case 16:
02952                {
02953 #if defined(PNG_READ_GAMMA_SUPPORTED)
02954                   if (gamma_16 != NULL)
02955                   {
02956                      sp = row;
02957                      for (i = 0; i < row_width; i++, sp += 2)
02958                      {
02959                         png_uint_16 v;
02960 
02961                         v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
02962                         if (v == trans_values->gray)
02963                         {
02964                            /* Background is already in screen gamma */
02965                            *sp = (png_byte)((background->gray >> 8) & 0xff);
02966                            *(sp + 1) = (png_byte)(background->gray & 0xff);
02967                         }
02968                         else
02969                         {
02970                            v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
02971                            *sp = (png_byte)((v >> 8) & 0xff);
02972                            *(sp + 1) = (png_byte)(v & 0xff);
02973                         }
02974                      }
02975                   }
02976                   else
02977 #endif
02978                   {
02979                      sp = row;
02980                      for (i = 0; i < row_width; i++, sp += 2)
02981                      {
02982                         png_uint_16 v;
02983 
02984                         v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
02985                         if (v == trans_values->gray)
02986                         {
02987                            *sp = (png_byte)((background->gray >> 8) & 0xff);
02988                            *(sp + 1) = (png_byte)(background->gray & 0xff);
02989                         }
02990                      }
02991                   }
02992                   break;
02993                }
02994             }
02995             break;
02996          }
02997 
02998          case PNG_COLOR_TYPE_RGB:
02999          {
03000             if (row_info->bit_depth == 8)
03001             {
03002 #if defined(PNG_READ_GAMMA_SUPPORTED)
03003                if (gamma_table != NULL)
03004                {
03005                   sp = row;
03006                   for (i = 0; i < row_width; i++, sp += 3)
03007                   {
03008                      if (*sp == trans_values->red &&
03009                         *(sp + 1) == trans_values->green &&
03010                         *(sp + 2) == trans_values->blue)
03011                      {
03012                         *sp = (png_byte)background->red;
03013                         *(sp + 1) = (png_byte)background->green;
03014                         *(sp + 2) = (png_byte)background->blue;
03015                      }
03016                      else
03017                      {
03018                         *sp = gamma_table[*sp];
03019                         *(sp + 1) = gamma_table[*(sp + 1)];
03020                         *(sp + 2) = gamma_table[*(sp + 2)];
03021                      }
03022                   }
03023                }
03024                else
03025 #endif
03026                {
03027                   sp = row;
03028                   for (i = 0; i < row_width; i++, sp += 3)
03029                   {
03030                      if (*sp == trans_values->red &&
03031                         *(sp + 1) == trans_values->green &&
03032                         *(sp + 2) == trans_values->blue)
03033                      {
03034                         *sp = (png_byte)background->red;
03035                         *(sp + 1) = (png_byte)background->green;
03036                         *(sp + 2) = (png_byte)background->blue;
03037                      }
03038                   }
03039                }
03040             }
03041             else /* if (row_info->bit_depth == 16) */
03042             {
03043 #if defined(PNG_READ_GAMMA_SUPPORTED)
03044                if (gamma_16 != NULL)
03045                {
03046                   sp = row;
03047                   for (i = 0; i < row_width; i++, sp += 6)
03048                   {
03049                      png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
03050                      png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
03051                      png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5));
03052                      if (r == trans_values->red && g == trans_values->green &&
03053                         b == trans_values->blue)
03054                      {
03055                         /* Background is already in screen gamma */
03056                         *sp = (png_byte)((background->red >> 8) & 0xff);
03057                         *(sp + 1) = (png_byte)(background->red & 0xff);
03058                         *(sp + 2) = (png_byte)((background->green >> 8) & 0xff);
03059                         *(sp + 3) = (png_byte)(background->green & 0xff);
03060                         *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff);
03061                         *(sp + 5) = (png_byte)(background->blue & 0xff);
03062                      }
03063                      else
03064                      {
03065                         png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
03066                         *sp = (png_byte)((v >> 8) & 0xff);
03067                         *(sp + 1) = (png_byte)(v & 0xff);
03068                         v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
03069                         *(sp + 2) = (png_byte)((v >> 8) & 0xff);
03070                         *(sp + 3) = (png_byte)(v & 0xff);
03071                         v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
03072                         *(sp + 4) = (png_byte)((v >> 8) & 0xff);
03073                         *(sp + 5) = (png_byte)(v & 0xff);
03074                      }
03075                   }
03076                }
03077                else
03078 #endif
03079                {
03080                   sp = row;
03081                   for (i = 0; i < row_width; i++, sp += 6)
03082                   {
03083                      png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp+1));
03084                      png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
03085                      png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5));
03086 
03087                      if (r == trans_values->red && g == trans_values->green &&
03088                         b == trans_values->blue)
03089                      {
03090                         *sp = (png_byte)((background->red >> 8) & 0xff);
03091                         *(sp + 1) = (png_byte)(background->red & 0xff);
03092                         *(sp + 2) = (png_byte)((background->green >> 8) & 0xff);
03093                         *(sp + 3) = (png_byte)(background->green & 0xff);
03094                         *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff);
03095                         *(sp + 5) = (png_byte)(background->blue & 0xff);
03096                      }
03097                   }
03098                }
03099             }
03100             break;
03101          }
03102 
03103          case PNG_COLOR_TYPE_GRAY_ALPHA:
03104          {
03105             if (row_info->bit_depth == 8)
03106             {
03107 #if defined(PNG_READ_GAMMA_SUPPORTED)
03108                if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
03109                    gamma_table != NULL)
03110                {
03111                   sp = row;
03112                   dp = row;
03113                   for (i = 0; i < row_width; i++, sp += 2, dp++)
03114                   {
03115                      png_uint_16 a = *(sp + 1);
03116 
03117                      if (a == 0xff)
03118                      {
03119                         *dp = gamma_table[*sp];
03120                      }
03121                      else if (a == 0)
03122                      {
03123                         /* Background is already in screen gamma */
03124                         *dp = (png_byte)background->gray;
03125                      }
03126                      else
03127                      {
03128                         png_byte v, w;
03129 
03130                         v = gamma_to_1[*sp];
03131                         png_composite(w, v, a, background_1->gray);
03132                         *dp = gamma_from_1[w];
03133                      }
03134                   }
03135                }
03136                else
03137 #endif
03138                {
03139                   sp = row;
03140                   dp = row;
03141                   for (i = 0; i < row_width; i++, sp += 2, dp++)
03142                   {
03143                      png_byte a = *(sp + 1);
03144 
03145                      if (a == 0xff)
03146                      {
03147                         *dp = *sp;
03148                      }
03149 #if defined(PNG_READ_GAMMA_SUPPORTED)
03150                      else if (a == 0)
03151                      {
03152                         *dp = (png_byte)background->gray;
03153                      }
03154                      else
03155                      {
03156                         png_composite(*dp, *sp, a, background_1->gray);
03157                      }
03158 #else
03159                      *dp = (png_byte)background->gray;
03160 #endif
03161                   }
03162                }
03163             }
03164             else /* if (png_ptr->bit_depth == 16) */
03165             {
03166 #if defined(PNG_READ_GAMMA_SUPPORTED)
03167                if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
03168                    gamma_16_to_1 != NULL)
03169                {
03170                   sp = row;
03171                   dp = row;
03172                   for (i = 0; i < row_width; i++, sp += 4, dp += 2)
03173                   {
03174                      png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
03175 
03176                      if (a == (png_uint_16)0xffff)
03177                      {
03178                         png_uint_16 v;
03179 
03180                         v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
03181                         *dp = (png_byte)((v >> 8) & 0xff);
03182                         *(dp + 1) = (png_byte)(v & 0xff);
03183                      }
03184 #if defined(PNG_READ_GAMMA_SUPPORTED)
03185                      else if (a == 0)
03186 #else
03187                      else
03188 #endif
03189                      {
03190                         /* Background is already in screen gamma */
03191                         *dp = (png_byte)((background->gray >> 8) & 0xff);
03192                         *(dp + 1) = (png_byte)(background->gray & 0xff);
03193                      }
03194 #if defined(PNG_READ_GAMMA_SUPPORTED)
03195                      else
03196                      {
03197                         png_uint_16 g, v, w;
03198 
03199                         g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
03200                         png_composite_16(v, g, a, background_1->gray);
03201                         w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8];
03202                         *dp = (png_byte)((w >> 8) & 0xff);
03203                         *(dp + 1) = (png_byte)(w & 0xff);
03204                      }
03205 #endif
03206                   }
03207                }
03208                else
03209 #endif
03210                {
03211                   sp = row;
03212                   dp = row;
03213                   for (i = 0; i < row_width; i++, sp += 4, dp += 2)
03214                   {
03215                      png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
03216                      if (a == (png_uint_16)0xffff)
03217                      {
03218                         png_memcpy(dp, sp, 2);
03219                      }
03220 #if defined(PNG_READ_GAMMA_SUPPORTED)
03221                      else if (a == 0)
03222 #else
03223                      else
03224 #endif
03225                      {
03226                         *dp = (png_byte)((background->gray >> 8) & 0xff);
03227                         *(dp + 1) = (png_byte)(background->gray & 0xff);
03228                      }
03229 #if defined(PNG_READ_GAMMA_SUPPORTED)
03230                      else
03231                      {
03232                         png_uint_16 g, v;
03233 
03234                         g = (png_uint_16)(((*sp) << 8) + *(sp + 1));
03235                         png_composite_16(v, g, a, background_1->gray);
03236                         *dp = (png_byte)((v >> 8) & 0xff);
03237                         *(dp + 1) = (png_byte)(v & 0xff);
03238                      }
03239 #endif
03240                   }
03241                }
03242             }
03243             break;
03244          }
03245 
03246          case PNG_COLOR_TYPE_RGB_ALPHA:
03247          {
03248             if (row_info->bit_depth == 8)
03249             {
03250 #if defined(PNG_READ_GAMMA_SUPPORTED)
03251                if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
03252                    gamma_table != NULL)
03253                {
03254                   sp = row;
03255                   dp = row;
03256                   for (i = 0; i < row_width; i++, sp += 4, dp += 3)
03257                   {
03258                      png_byte a = *(sp + 3);
03259 
03260                      if (a == 0xff)
03261                      {
03262                         *dp = gamma_table[*sp];
03263                         *(dp + 1) = gamma_table[*(sp + 1)];
03264                         *(dp + 2) = gamma_table[*(sp + 2)];
03265                      }
03266                      else if (a == 0)
03267                      {
03268                         /* Background is already in screen gamma */
03269                         *dp = (png_byte)background->red;
03270                         *(dp + 1) = (png_byte)background->green;
03271                         *(dp + 2) = (png_byte)background->blue;
03272                      }
03273                      else
03274                      {
03275                         png_byte v, w;
03276 
03277                         v = gamma_to_1[*sp];
03278                         png_composite(w, v, a, background_1->red);
03279                         *dp = gamma_from_1[w];
03280                         v = gamma_to_1[*(sp + 1)];
03281                         png_composite(w, v, a, background_1->green);
03282                         *(dp + 1) = gamma_from_1[w];
03283                         v = gamma_to_1[*(sp + 2)];
03284                         png_composite(w, v, a, background_1->blue);
03285                         *(dp + 2) = gamma_from_1[w];
03286                      }
03287                   }
03288                }
03289                else
03290 #endif
03291                {
03292                   sp = row;
03293                   dp = row;
03294                   for (i = 0; i < row_width; i++, sp += 4, dp += 3)
03295                   {
03296                      png_byte a = *(sp + 3);
03297 
03298                      if (a == 0xff)
03299                      {
03300                         *dp = *sp;
03301                         *(dp + 1) = *(sp + 1);
03302                         *(dp + 2) = *(sp + 2);
03303                      }
03304                      else if (a == 0)
03305                      {
03306                         *dp = (png_byte)background->red;
03307                         *(dp + 1) = (png_byte)background->green;
03308                         *(dp + 2) = (png_byte)background->blue;
03309                      }
03310                      else
03311                      {
03312                         png_composite(*dp, *sp, a, background->red);
03313                         png_composite(*(dp + 1), *(sp + 1), a,
03314                            background->green);
03315                         png_composite(*(dp + 2), *(sp + 2), a,
03316                            background->blue);
03317                      }
03318                   }
03319                }
03320             }
03321             else /* if (row_info->bit_depth == 16) */
03322             {
03323 #if defined(PNG_READ_GAMMA_SUPPORTED)
03324                if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
03325                    gamma_16_to_1 != NULL)
03326                {
03327                   sp = row;
03328                   dp = row;
03329                   for (i = 0; i < row_width; i++, sp += 8, dp += 6)
03330                   {
03331                      png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
03332                          << 8) + (png_uint_16)(*(sp + 7)));
03333                      if (a == (png_uint_16)0xffff)
03334                      {
03335                         png_uint_16 v;
03336 
03337                         v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
03338                         *dp = (png_byte)((v >> 8) & 0xff);
03339                         *(dp + 1) = (png_byte)(v & 0xff);
03340                         v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
03341                         *(dp + 2) = (png_byte)((v >> 8) & 0xff);
03342                         *(dp + 3) = (png_byte)(v & 0xff);
03343                         v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
03344                         *(dp + 4) = (png_byte)((v >> 8) & 0xff);
03345                         *(dp + 5) = (png_byte)(v & 0xff);
03346                      }
03347                      else if (a == 0)
03348                      {
03349                         /* Background is already in screen gamma */
03350                         *dp = (png_byte)((background->red >> 8) & 0xff);
03351                         *(dp + 1) = (png_byte)(background->red & 0xff);
03352                         *(dp + 2) = (png_byte)((background->green >> 8) & 0xff);
03353                         *(dp + 3) = (png_byte)(background->green & 0xff);
03354                         *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff);
03355                         *(dp + 5) = (png_byte)(background->blue & 0xff);
03356                      }
03357                      else
03358                      {
03359                         png_uint_16 v, w, x;
03360 
03361                         v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
03362                         png_composite_16(w, v, a, background_1->red);
03363                         x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
03364                         *dp = (png_byte)((x >> 8) & 0xff);
03365                         *(dp + 1) = (png_byte)(x & 0xff);
03366                         v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)];
03367                         png_composite_16(w, v, a, background_1->green);
03368                         x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
03369                         *(dp + 2) = (png_byte)((x >> 8) & 0xff);
03370                         *(dp + 3) = (png_byte)(x & 0xff);
03371                         v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)];
03372                         png_composite_16(w, v, a, background_1->blue);
03373                         x = gamma_16_from_1[(w & 0xff) >> gamma_shift][w >> 8];
03374                         *(dp + 4) = (png_byte)((x >> 8) & 0xff);
03375                         *(dp + 5) = (png_byte)(x & 0xff);
03376                      }
03377                   }
03378                }
03379                else
03380 #endif
03381                {
03382                   sp = row;
03383                   dp = row;
03384                   for (i = 0; i < row_width; i++, sp += 8, dp += 6)
03385                   {
03386                      png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
03387                         << 8) + (png_uint_16)(*(sp + 7)));
03388                      if (a == (png_uint_16)0xffff)
03389                      {
03390                         png_memcpy(dp, sp, 6);
03391                      }
03392                      else if (a == 0)
03393                      {
03394                         *dp = (png_byte)((background->red >> 8) & 0xff);
03395                         *(dp + 1) = (png_byte)(background->red & 0xff);
03396                         *(dp + 2) = (png_byte)((background->green >> 8) & 0xff);
03397                         *(dp + 3) = (png_byte)(background->green & 0xff);
03398                         *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff);
03399                         *(dp + 5) = (png_byte)(background->blue & 0xff);
03400                      }
03401                      else
03402                      {
03403                         png_uint_16 v;
03404 
03405                         png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
03406                         png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
03407                             + *(sp + 3));
03408                         png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
03409                             + *(sp + 5));
03410 
03411                         png_composite_16(v, r, a, background->red);
03412                         *dp = (png_byte)((v >> 8) & 0xff);
03413                         *(dp + 1) = (png_byte)(v & 0xff);
03414                         png_composite_16(v, g, a, background->green);
03415                         *(dp + 2) = (png_byte)((v >> 8) & 0xff);
03416                         *(dp + 3) = (png_byte)(v & 0xff);
03417                         png_composite_16(v, b, a, background->blue);
03418                         *(dp + 4) = (png_byte)((v >> 8) & 0xff);
03419                         *(dp + 5) = (png_byte)(v & 0xff);
03420                      }
03421                   }
03422                }
03423             }
03424             break;
03425          }
03426       }
03427 
03428       if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
03429       {
03430          row_info->color_type &= ~PNG_COLOR_MASK_ALPHA;
03431          row_info->channels--;
03432          row_info->pixel_depth = (png_byte)(row_info->channels *
03433             row_info->bit_depth);
03434          row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
03435       }
03436    }
03437 }
03438 #endif
03439 
03440 #if defined(PNG_READ_GAMMA_SUPPORTED)
03441 /* Gamma correct the image, avoiding the alpha channel.  Make sure
03442  * you do this after you deal with the transparency issue on grayscale
03443  * or RGB images. If your bit depth is 8, use gamma_table, if it
03444  * is 16, use gamma_16_table and gamma_shift.  Build these with
03445  * build_gamma_table().
03446  */
03447 void /* PRIVATE */
03448 png_do_gamma(png_row_infop row_info, png_bytep row,
03449    png_bytep gamma_table, png_uint_16pp gamma_16_table,
03450    int gamma_shift)
03451 {
03452    png_bytep sp;
03453    png_uint_32 i;
03454    png_uint_32 row_width=row_info->width;
03455 
03456    png_debug(1, "in png_do_gamma");
03457    if (
03458 #if defined(PNG_USELESS_TESTS_SUPPORTED)
03459        row != NULL && row_info != NULL &&
03460 #endif
03461        ((row_info->bit_depth <= 8 && gamma_table != NULL) ||
03462         (row_info->bit_depth == 16 && gamma_16_table != NULL)))
03463    {
03464       switch (row_info->color_type)
03465       {
03466          case PNG_COLOR_TYPE_RGB:
03467          {
03468             if (row_info->bit_depth == 8)
03469             {
03470                sp = row;
03471                for (i = 0; i < row_width; i++)
03472                {
03473                   *sp = gamma_table[*sp];
03474                   sp++;
03475                   *sp = gamma_table[*sp];
03476                   sp++;
03477                   *sp = gamma_table[*sp];
03478                   sp++;
03479                }
03480             }
03481             else /* if (row_info->bit_depth == 16) */
03482             {
03483                sp = row;
03484                for (i = 0; i < row_width; i++)
03485                {
03486                   png_uint_16 v;
03487 
03488                   v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
03489                   *sp = (png_byte)((v >> 8) & 0xff);
03490                   *(sp + 1) = (png_byte)(v & 0xff);
03491                   sp += 2;
03492                   v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
03493                   *sp = (png_byte)((v >> 8) & 0xff);
03494                   *(sp + 1) = (png_byte)(v & 0xff);
03495                   sp += 2;
03496                   v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
03497                   *sp = (png_byte)((v >> 8) & 0xff);
03498                   *(sp + 1) = (png_byte)(v & 0xff);
03499                   sp += 2;
03500                }
03501             }
03502             break;
03503          }
03504 
03505          case PNG_COLOR_TYPE_RGB_ALPHA:
03506          {
03507             if (row_info->bit_depth == 8)
03508             {
03509                sp = row;
03510                for (i = 0; i < row_width; i++)
03511                {
03512                   *sp = gamma_table[*sp];
03513                   sp++;
03514                   *sp = gamma_table[*sp];
03515                   sp++;
03516                   *sp = gamma_table[*sp];
03517                   sp++;
03518                   sp++;
03519                }
03520             }
03521             else /* if (row_info->bit_depth == 16) */
03522             {
03523                sp = row;
03524                for (i = 0; i < row_width; i++)
03525                {
03526                   png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
03527                   *sp = (png_byte)((v >> 8) & 0xff);
03528                   *(sp + 1) = (png_byte)(v & 0xff);
03529                   sp += 2;
03530                   v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
03531                   *sp = (png_byte)((v >> 8) & 0xff);
03532                   *(sp + 1) = (png_byte)(v & 0xff);
03533                   sp += 2;
03534                   v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
03535                   *sp = (png_byte)((v >> 8) & 0xff);
03536                   *(sp + 1) = (png_byte)(v & 0xff);
03537                   sp += 4;
03538                }
03539             }
03540             break;
03541          }
03542 
03543          case PNG_COLOR_TYPE_GRAY_ALPHA:
03544          {
03545             if (row_info->bit_depth == 8)
03546             {
03547                sp = row;
03548                for (i = 0; i < row_width; i++)
03549                {
03550                   *sp = gamma_table[*sp];
03551                   sp += 2;
03552                }
03553             }
03554             else /* if (row_info->bit_depth == 16) */
03555             {
03556                sp = row;
03557                for (i = 0; i < row_width; i++)
03558                {
03559                   png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
03560                   *sp = (png_byte)((v >> 8) & 0xff);
03561                   *(sp + 1) = (png_byte)(v & 0xff);
03562                   sp += 4;
03563                }
03564             }
03565             break;
03566          }
03567 
03568          case PNG_COLOR_TYPE_GRAY:
03569          {
03570             if (row_info->bit_depth == 2)
03571             {
03572                sp = row;
03573                for (i = 0; i < row_width; i += 4)
03574                {
03575                   int a = *sp & 0xc0;
03576                   int b = *sp & 0x30;
03577                   int c = *sp & 0x0c;
03578                   int d = *sp & 0x03;
03579 
03580                   *sp = (png_byte)(
03581                         ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)])   ) & 0xc0)|
03582                         ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)|
03583                         ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)|
03584                         ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) ));
03585                   sp++;
03586                }
03587             }
03588 
03589             if (row_info->bit_depth == 4)
03590             {
03591                sp = row;
03592                for (i = 0; i < row_width; i += 2)
03593                {
03594                   int msb = *sp & 0xf0;
03595                   int lsb = *sp & 0x0f;
03596 
03597                   *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0)
03598                           | (((int)gamma_table[(lsb << 4) | lsb]) >> 4));
03599                   sp++;
03600                }
03601             }
03602 
03603             else if (row_info->bit_depth == 8)
03604             {
03605                sp = row;
03606                for (i = 0; i < row_width; i++)
03607                {
03608                   *sp = gamma_table[*sp];
03609                   sp++;
03610                }
03611             }
03612 
03613             else if (row_info->bit_depth == 16)
03614             {
03615                sp = row;
03616                for (i = 0; i < row_width; i++)
03617                {
03618                   png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
03619                   *sp = (png_byte)((v >> 8) & 0xff);
03620                   *(sp + 1) = (png_byte)(v & 0xff);
03621                   sp += 2;
03622                }
03623             }
03624             break;
03625          }
03626       }
03627    }
03628 }
03629 #endif
03630 
03631 #if defined(PNG_READ_EXPAND_SUPPORTED)
03632 /* Expands a palette row to an RGB or RGBA row depending
03633  * upon whether you supply trans and num_trans.
03634  */
03635 void /* PRIVATE */
03636 png_do_expand_palette(png_row_infop row_info, png_bytep row,
03637    png_colorp palette, png_bytep trans, int num_trans)
03638 {
03639    int shift, value;
03640    png_bytep sp, dp;
03641    png_uint_32 i;
03642    png_uint_32 row_width=row_info->width;
03643 
03644    png_debug(1, "in png_do_expand_palette");
03645    if (
03646 #if defined(PNG_USELESS_TESTS_SUPPORTED)
03647        row != NULL && row_info != NULL &&
03648 #endif
03649        row_info->color_type == PNG_COLOR_TYPE_PALETTE)
03650    {
03651       if (row_info->bit_depth < 8)
03652       {
03653          switch (row_info->bit_depth)
03654          {
03655             case 1:
03656             {
03657                sp = row + (png_size_t)((row_width - 1) >> 3);
03658                dp = row + (png_size_t)row_width - 1;
03659                shift = 7 - (int)((row_width + 7) & 0x07);
03660                for (i = 0; i < row_width; i++)
03661                {
03662                   if ((*sp >> shift) & 0x01)
03663                      *dp = 1;
03664                   else
03665                      *dp = 0;
03666                   if (shift == 7)
03667                   {
03668                      shift = 0;
03669                      sp--;
03670                   }
03671                   else
03672                      shift++;
03673 
03674                   dp--;
03675                }
03676                break;
03677             }
03678 
03679             case 2:
03680             {
03681                sp = row + (png_size_t)((row_width - 1) >> 2);
03682                dp = row + (png_size_t)row_width - 1;
03683                shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
03684                for (i = 0; i < row_width; i++)
03685                {
03686                   value = (*sp >> shift) & 0x03;
03687                   *dp = (png_byte)value;
03688                   if (shift == 6)
03689                   {
03690                      shift = 0;
03691                      sp--;
03692                   }
03693                   else
03694                      shift += 2;
03695 
03696                   dp--;
03697                }
03698                break;
03699             }
03700 
03701             case 4:
03702             {
03703                sp = row + (png_size_t)((row_width - 1) >> 1);
03704                dp = row + (png_size_t)row_width - 1;
03705                shift = (int)((row_width & 0x01) << 2);
03706                for (i = 0; i < row_width; i++)
03707                {
03708                   value = (*sp >> shift) & 0x0f;
03709                   *dp = (png_byte)value;
03710                   if (shift == 4)
03711                   {
03712                      shift = 0;
03713                      sp--;
03714                   }
03715                   else
03716                      shift += 4;
03717 
03718                   dp--;
03719                }
03720                break;
03721             }
03722          }
03723          row_info->bit_depth = 8;
03724          row_info->pixel_depth = 8;
03725          row_info->rowbytes = row_width;
03726       }
03727       switch (row_info->bit_depth)
03728       {
03729          case 8:
03730          {
03731             if (trans != NULL)
03732             {
03733                sp = row + (png_size_t)row_width - 1;
03734                dp = row + (png_size_t)(row_width << 2) - 1;
03735 
03736                for (i = 0; i < row_width; i++)
03737                {
03738                   if ((int)(*sp) >= num_trans)
03739                      *dp-- = 0xff;
03740                   else
03741                      *dp-- = trans[*sp];
03742                   *dp-- = palette[*sp].blue;
03743                   *dp-- = palette[*sp].green;
03744                   *dp-- = palette[*sp].red;
03745                   sp--;
03746                }
03747                row_info->bit_depth = 8;
03748                row_info->pixel_depth = 32;
03749                row_info->rowbytes = row_width * 4;
03750                row_info->color_type = 6;
03751                row_info->channels = 4;
03752             }
03753             else
03754             {
03755                sp = row + (png_size_t)row_width - 1;
03756                dp = row + (png_size_t)(row_width * 3) - 1;
03757 
03758                for (i = 0; i < row_width; i++)
03759                {
03760                   *dp-- = palette[*sp].blue;
03761                   *dp-- = palette[*sp].green;
03762                   *dp-- = palette[*sp].red;
03763                   sp--;
03764                }
03765 
03766                row_info->bit_depth = 8;
03767                row_info->pixel_depth = 24;
03768                row_info->rowbytes = row_width * 3;
03769                row_info->color_type = 2;
03770                row_info->channels = 3;
03771             }
03772             break;
03773          }
03774       }
03775    }
03776 }
03777 
03778 /* If the bit depth < 8, it is expanded to 8.  Also, if the already
03779  * expanded transparency value is supplied, an alpha channel is built.
03780  */
03781 void /* PRIVATE */
03782 png_do_expand(png_row_infop row_info, png_bytep row,
03783    png_color_16p trans_value)
03784 {
03785    int shift, value;
03786    png_bytep sp, dp;
03787    png_uint_32 i;
03788    png_uint_32 row_width=row_info->width;
03789 
03790    png_debug(1, "in png_do_expand");
03791 #if defined(PNG_USELESS_TESTS_SUPPORTED)
03792    if (row != NULL && row_info != NULL)
03793 #endif
03794    {
03795       if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
03796       {
03797          png_uint_16 gray = (png_uint_16)(trans_value ? trans_value->gray : 0);
03798 
03799          if (row_info->bit_depth < 8)
03800          {
03801             switch (row_info->bit_depth)
03802             {
03803                case 1:
03804                {
03805                   gray = (png_uint_16)((gray&0x01)*0xff);
03806                   sp = row + (png_size_t)((row_width - 1) >> 3);
03807                   dp = row + (png_size_t)row_width - 1;
03808                   shift = 7 - (int)((row_width + 7) & 0x07);
03809                   for (i = 0; i < row_width; i++)
03810                   {
03811                      if ((*sp >> shift) & 0x01)
03812                         *dp = 0xff;
03813                      else
03814                         *dp = 0;
03815                      if (shift == 7)
03816                      {
03817                         shift = 0;
03818                         sp--;
03819                      }
03820                      else
03821                         shift++;
03822 
03823                      dp--;
03824                   }
03825                   break;
03826                }
03827 
03828                case 2:
03829                {
03830                   gray = (png_uint_16)((gray&0x03)*0x55);
03831                   sp = row + (png_size_t)((row_width - 1) >> 2);
03832                   dp = row + (png_size_t)row_width - 1;
03833                   shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
03834                   for (i = 0; i < row_width; i++)
03835                   {
03836                      value = (*sp >> shift) & 0x03;
03837                      *dp = (png_byte)(value | (value << 2) | (value << 4) |
03838                         (value << 6));
03839                      if (shift == 6)
03840                      {
03841                         shift = 0;
03842                         sp--;
03843                      }
03844                      else
03845                         shift += 2;
03846 
03847                      dp--;
03848                   }
03849                   break;
03850                }
03851 
03852                case 4:
03853                {
03854                   gray = (png_uint_16)((gray&0x0f)*0x11);
03855                   sp = row + (png_size_t)((row_width - 1) >> 1);
03856                   dp = row + (png_size_t)row_width - 1;
03857                   shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
03858                   for (i = 0; i < row_width; i++)
03859                   {
03860                      value = (*sp >> shift) & 0x0f;
03861                      *dp = (png_byte)(value | (value << 4));
03862                      if (shift == 4)
03863                      {
03864                         shift = 0;
03865                         sp--;
03866                      }
03867                      else
03868                         shift = 4;
03869 
03870                      dp--;
03871                   }
03872                   break;
03873                }
03874             }
03875 
03876             row_info->bit_depth = 8;
03877             row_info->pixel_depth = 8;
03878             row_info->rowbytes = row_width;
03879          }
03880 
03881          if (trans_value != NULL)
03882          {
03883             if (row_info->bit_depth == 8)
03884             {
03885                gray = gray & 0xff;
03886                sp = row + (png_size_t)row_width - 1;
03887                dp = row + (png_size_t)(row_width << 1) - 1;
03888                for (i = 0; i < row_width; i++)
03889                {
03890                   if (*sp == gray)
03891                      *dp-- = 0;
03892                   else
03893                      *dp-- = 0xff;
03894                   *dp-- = *sp--;
03895                }
03896             }
03897 
03898             else if (row_info->bit_depth == 16)
03899             {
03900                png_byte gray_high = (gray >> 8) & 0xff;
03901                png_byte gray_low = gray & 0xff;
03902                sp = row + row_info->rowbytes - 1;
03903                dp = row + (row_info->rowbytes << 1) - 1;
03904                for (i = 0; i < row_width; i++)
03905                {
03906                   if (*(sp - 1) == gray_high && *(sp) == gray_low)
03907                   {
03908                      *dp-- = 0;
03909                      *dp-- = 0;
03910                   }
03911                   else
03912                   {
03913                      *dp-- = 0xff;
03914                      *dp-- = 0xff;
03915                   }
03916                   *dp-- = *sp--;
03917                   *dp-- = *sp--;
03918                }
03919             }
03920 
03921             row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
03922             row_info->channels = 2;
03923             row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1);
03924             row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
03925                row_width);
03926          }
03927       }
03928       else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_value)
03929       {
03930          if (row_info->bit_depth == 8)
03931          {
03932             png_byte red = trans_value->red & 0xff;
03933             png_byte green = trans_value->green & 0xff;
03934             png_byte blue = trans_value->blue & 0xff;
03935             sp = row + (png_size_t)row_info->rowbytes - 1;
03936             dp = row + (png_size_t)(row_width << 2) - 1;
03937             for (i = 0; i < row_width; i++)
03938             {
03939                if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue)
03940                   *dp-- = 0;
03941                else
03942                   *dp-- = 0xff;
03943                *dp-- = *sp--;
03944                *dp-- = *sp--;
03945                *dp-- = *sp--;
03946             }
03947          }
03948          else if (row_info->bit_depth == 16)
03949          {
03950             png_byte red_high = (trans_value->red >> 8) & 0xff;
03951             png_byte green_high = (trans_value->green >> 8) & 0xff;
03952             png_byte blue_high = (trans_value->blue >> 8) & 0xff;
03953             png_byte red_low = trans_value->red & 0xff;
03954             png_byte green_low = trans_value->green & 0xff;
03955             png_byte blue_low = trans_value->blue & 0xff;
03956             sp = row + row_info->rowbytes - 1;
03957             dp = row + (png_size_t)(row_width << 3) - 1;
03958             for (i = 0; i < row_width; i++)
03959             {
03960                if (*(sp - 5) == red_high &&
03961                   *(sp - 4) == red_low &&
03962                   *(sp - 3) == green_high &&
03963                   *(sp - 2) == green_low &&
03964                   *(sp - 1) == blue_high &&
03965                   *(sp    ) == blue_low)
03966                {
03967                   *dp-- = 0;
03968                   *dp-- = 0;
03969                }
03970                else
03971                {
03972                   *dp-- = 0xff;
03973                   *dp-- = 0xff;
03974                }
03975                *dp-- = *sp--;
03976                *dp-- = *sp--;
03977                *dp-- = *sp--;
03978                *dp-- = *sp--;
03979                *dp-- = *sp--;
03980                *dp-- = *sp--;
03981             }
03982          }
03983          row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
03984          row_info->channels = 4;
03985          row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2);
03986          row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
03987       }
03988    }
03989 }
03990 #endif
03991 
03992 #if defined(PNG_READ_DITHER_SUPPORTED)
03993 void /* PRIVATE */
03994 png_do_dither(png_row_infop row_info, png_bytep row,
03995     png_bytep palette_lookup, png_bytep dither_lookup)
03996 {
03997    png_bytep sp, dp;
03998    png_uint_32 i;
03999    png_uint_32 row_width=row_info->width;
04000 
04001    png_debug(1, "in png_do_dither");
04002 #if defined(PNG_USELESS_TESTS_SUPPORTED)
04003    if (row != NULL && row_info != NULL)
04004 #endif
04005    {
04006       if (row_info->color_type == PNG_COLOR_TYPE_RGB &&
04007          palette_lookup && row_info->bit_depth == 8)
04008       {
04009          int r, g, b, p;
04010          sp = row;
04011          dp = row;
04012          for (i = 0; i < row_width; i++)
04013          {
04014             r = *sp++;
04015             g = *sp++;
04016             b = *sp++;
04017 
04018             /* This looks real messy, but the compiler will reduce
04019              * it down to a reasonable formula.  For example, with
04020              * 5 bits per color, we get:
04021              * p = (((r >> 3) & 0x1f) << 10) |
04022              *    (((g >> 3) & 0x1f) << 5) |
04023              *    ((b >> 3) & 0x1f);
04024              */
04025             p = (((r >> (8 - PNG_DITHER_RED_BITS)) &
04026                ((1 << PNG_DITHER_RED_BITS) - 1)) <<
04027                (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) |
04028                (((g >> (8 - PNG_DITHER_GREEN_BITS)) &
04029                ((1 << PNG_DITHER_GREEN_BITS) - 1)) <<
04030                (PNG_DITHER_BLUE_BITS)) |
04031                ((b >> (8 - PNG_DITHER_BLUE_BITS)) &
04032                ((1 << PNG_DITHER_BLUE_BITS) - 1));
04033 
04034             *dp++ = palette_lookup[p];
04035          }
04036          row_info->color_type = PNG_COLOR_TYPE_PALETTE;
04037          row_info->channels = 1;
04038          row_info->pixel_depth = row_info->bit_depth;
04039          row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
04040       }
04041       else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
04042          palette_lookup != NULL && row_info->bit_depth == 8)
04043       {
04044          int r, g, b, p;
04045          sp = row;
04046          dp = row;
04047          for (i = 0; i < row_width; i++)
04048          {
04049             r = *sp++;
04050             g = *sp++;
04051             b = *sp++;
04052             sp++;
04053 
04054             p = (((r >> (8 - PNG_DITHER_RED_BITS)) &
04055                ((1 << PNG_DITHER_RED_BITS) - 1)) <<
04056                (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) |
04057                (((g >> (8 - PNG_DITHER_GREEN_BITS)) &
04058                ((1 << PNG_DITHER_GREEN_BITS) - 1)) <<
04059                (PNG_DITHER_BLUE_BITS)) |
04060                ((b >> (8 - PNG_DITHER_BLUE_BITS)) &
04061                ((1 << PNG_DITHER_BLUE_BITS) - 1));
04062 
04063             *dp++ = palette_lookup[p];
04064          }
04065          row_info->color_type = PNG_COLOR_TYPE_PALETTE;
04066          row_info->channels = 1;
04067          row_info->pixel_depth = row_info->bit_depth;
04068          row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
04069       }
04070       else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
04071          dither_lookup && row_info->bit_depth == 8)
04072       {
04073          sp = row;
04074          for (i = 0; i < row_width; i++, sp++)
04075          {
04076             *sp = dither_lookup[*sp];
04077          }
04078       }
04079    }
04080 }
04081 #endif
04082 
04083 #ifdef PNG_FLOATING_POINT_SUPPORTED
04084 #if defined(PNG_READ_GAMMA_SUPPORTED)
04085 static PNG_CONST int png_gamma_shift[] =
04086    {0x10, 0x21, 0x42, 0x84, 0x110, 0x248, 0x550, 0xff0, 0x00};
04087 
04088 /* We build the 8- or 16-bit gamma tables here.  Note that for 16-bit
04089  * tables, we don't make a full table if we are reducing to 8-bit in
04090  * the future.  Note also how the gamma_16 tables are segmented so that
04091  * we don't need to allocate > 64K chunks for a full 16-bit table.
04092  */
04093 void /* PRIVATE */
04094 png_build_gamma_table(png_structp png_ptr)
04095 {
04096   png_debug(1, "in png_build_gamma_table");
04097 
04098   if (png_ptr->bit_depth <= 8)
04099   {
04100      int i;
04101      double g;
04102 
04103      if (png_ptr->screen_gamma > .000001)
04104         g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
04105 
04106      else
04107         g = 1.0;
04108 
04109      png_ptr->gamma_table = (png_bytep)png_malloc(png_ptr,
04110         (png_uint_32)256);
04111 
04112      for (i = 0; i < 256; i++)
04113      {
04114         png_ptr->gamma_table[i] = (png_byte)(pow((double)i / 255.0,
04115            g) * 255.0 + .5);
04116      }
04117 
04118 #if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
04119    defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
04120      if (png_ptr->transformations & ((PNG_BACKGROUND) | PNG_RGB_TO_GRAY))
04121      {
04122 
04123         g = 1.0 / (png_ptr->gamma);
04124 
04125         png_ptr->gamma_to_1 = (png_bytep)png_malloc(png_ptr,
04126            (png_uint_32)256);
04127 
04128         for (i = 0; i < 256; i++)
04129         {
04130            png_ptr->gamma_to_1[i] = (png_byte)(pow((double)i / 255.0,
04131               g) * 255.0 + .5);
04132         }
04133 
04134 
04135         png_ptr->gamma_from_1 = (png_bytep)png_malloc(png_ptr,
04136            (png_uint_32)256);
04137 
04138         if (png_ptr->screen_gamma > 0.000001)
04139            g = 1.0 / png_ptr->screen_gamma;
04140 
04141         else
04142            g = png_ptr->gamma;   /* Probably doing rgb_to_gray */
04143 
04144         for (i = 0; i < 256; i++)
04145         {
04146            png_ptr->gamma_from_1[i] = (png_byte)(pow((double)i / 255.0,
04147               g) * 255.0 + .5);
04148 
04149         }
04150      }
04151 #endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
04152   }
04153   else
04154   {
04155      double g;
04156      int i, j, shift, num;
04157      int sig_bit;
04158      png_uint_32 ig;
04159 
04160      if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
04161      {
04162         sig_bit = (int)png_ptr->sig_bit.red;
04163 
04164         if ((int)png_ptr->sig_bit.green > sig_bit)
04165            sig_bit = png_ptr->sig_bit.green;
04166 
04167         if ((int)png_ptr->sig_bit.blue > sig_bit)
04168            sig_bit = png_ptr->sig_bit.blue;
04169      }
04170      else
04171      {
04172         sig_bit = (int)png_ptr->sig_bit.gray;
04173      }
04174 
04175      if (sig_bit > 0)
04176         shift = 16 - sig_bit;
04177 
04178      else
04179         shift = 0;
04180 
04181      if (png_ptr->transformations & PNG_16_TO_8)
04182      {
04183         if (shift < (16 - PNG_MAX_GAMMA_8))
04184            shift = (16 - PNG_MAX_GAMMA_8);
04185      }
04186 
04187      if (shift > 8)
04188         shift = 8;
04189 
04190      if (shift < 0)
04191         shift = 0;
04192 
04193      png_ptr->gamma_shift = (png_byte)shift;
04194 
04195      num = (1 << (8 - shift));
04196 
04197      if (png_ptr->screen_gamma > .000001)
04198         g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
04199      else
04200         g = 1.0;
04201 
04202      png_ptr->gamma_16_table = (png_uint_16pp)png_malloc(png_ptr,
04203         (png_uint_32)(num * png_sizeof(png_uint_16p)));
04204      png_memset(png_ptr->gamma_16_table, 0, num * png_sizeof(png_uint_16p));
04205 
04206      if (png_ptr->transformations & (PNG_16_TO_8 | PNG_BACKGROUND))
04207      {
04208         double fin, fout;
04209         png_uint_32 last, max;
04210 
04211         for (i = 0; i < num; i++)
04212         {
04213            png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
04214               (png_uint_32)(256 * png_sizeof(png_uint_16)));
04215         }
04216 
04217         g = 1.0 / g;
04218         last = 0;
04219         for (i = 0; i < 256; i++)
04220         {
04221            fout = ((double)i + 0.5) / 256.0;
04222            fin = pow(fout, g);
04223            max = (png_uint_32)(fin * (double)((png_uint_32)num << 8));
04224            while (last <= max)
04225            {
04226               png_ptr->gamma_16_table[(int)(last & (0xff >> shift))]
04227                  [(int)(last >> (8 - shift))] = (png_uint_16)(
04228                  (png_uint_16)i | ((png_uint_16)i << 8));
04229               last++;
04230            }
04231         }
04232         while (last < ((png_uint_32)num << 8))
04233         {
04234            png_ptr->gamma_16_table[(int)(last & (0xff >> shift))]
04235               [(int)(last >> (8 - shift))] = (png_uint_16)65535L;
04236            last++;
04237         }
04238      }
04239      else
04240      {
04241         for (i = 0; i < num; i++)
04242         {
04243            png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
04244               (png_uint_32)(256 * png_sizeof(png_uint_16)));
04245 
04246            ig = (((png_uint_32)i * (png_uint_32)png_gamma_shift[shift]) >> 4);
04247 
04248            for (j = 0; j < 256; j++)
04249            {
04250               png_ptr->gamma_16_table[i][j] =
04251                  (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
04252                     65535.0, g) * 65535.0 + .5);
04253            }
04254         }
04255      }
04256 
04257 #if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
04258    defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
04259      if (png_ptr->transformations & (PNG_BACKGROUND | PNG_RGB_TO_GRAY))
04260      {
04261 
04262         g = 1.0 / (png_ptr->gamma);
04263 
04264         png_ptr->gamma_16_to_1 = (png_uint_16pp)png_malloc(png_ptr,
04265            (png_uint_32)(num * png_sizeof(png_uint_16p )));
04266         png_memset(png_ptr->gamma_16_to_1, 0, num * png_sizeof(png_uint_16p));
04267 
04268         for (i = 0; i < num; i++)
04269         {
04270            png_ptr->gamma_16_to_1[i] = (png_uint_16p)png_malloc(png_ptr,
04271               (png_uint_32)(256 * png_sizeof(png_uint_16)));
04272 
04273            ig = (((png_uint_32)i *
04274               (png_uint_32)png_gamma_shift[shift]) >> 4);
04275            for (j = 0; j < 256; j++)
04276            {
04277               png_ptr->gamma_16_to_1[i][j] =
04278                  (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
04279                     65535.0, g) * 65535.0 + .5);
04280            }
04281         }
04282 
04283         if (png_ptr->screen_gamma > 0.000001)
04284            g = 1.0 / png_ptr->screen_gamma;
04285 
04286         else
04287            g = png_ptr->gamma;   /* Probably doing rgb_to_gray */
04288 
04289         png_ptr->gamma_16_from_1 = (png_uint_16pp)png_malloc(png_ptr,
04290            (png_uint_32)(num * png_sizeof(png_uint_16p)));
04291         png_memset(png_ptr->gamma_16_from_1, 0,
04292            num * png_sizeof(png_uint_16p));
04293 
04294         for (i = 0; i < num; i++)
04295         {
04296            png_ptr->gamma_16_from_1[i] = (png_uint_16p)png_malloc(png_ptr,
04297               (png_uint_32)(256 * png_sizeof(png_uint_16)));
04298 
04299            ig = (((png_uint_32)i *
04300               (png_uint_32)png_gamma_shift[shift]) >> 4);
04301 
04302            for (j = 0; j < 256; j++)
04303            {
04304               png_ptr->gamma_16_from_1[i][j] =
04305                  (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
04306                     65535.0, g) * 65535.0 + .5);
04307            }
04308         }
04309      }
04310 #endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
04311   }
04312 }
04313 #endif
04314 /* To do: install integer version of png_build_gamma_table here */
04315 #endif
04316 
04317 #if defined(PNG_MNG_FEATURES_SUPPORTED)
04318 /* Undoes intrapixel differencing  */
04319 void /* PRIVATE */
04320 png_do_read_intrapixel(png_row_infop row_info, png_bytep row)
04321 {
04322    png_debug(1, "in png_do_read_intrapixel");
04323    if (
04324 #if defined(PNG_USELESS_TESTS_SUPPORTED)
04325        row != NULL && row_info != NULL &&
04326 #endif
04327        (row_info->color_type & PNG_COLOR_MASK_COLOR))
04328    {
04329       int bytes_per_pixel;
04330       png_uint_32 row_width = row_info->width;
04331       if (row_info->bit_depth == 8)
04332       {
04333          png_bytep rp;
04334          png_uint_32 i;
04335 
04336          if (row_info->color_type == PNG_COLOR_TYPE_RGB)
04337             bytes_per_pixel = 3;
04338 
04339          else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
04340             bytes_per_pixel = 4;
04341 
04342          else
04343             return;
04344 
04345          for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
04346          {
04347             *(rp) = (png_byte)((256 + *rp + *(rp+1))&0xff);
04348             *(rp+2) = (png_byte)((256 + *(rp+2) + *(rp+1))&0xff);
04349          }
04350       }
04351       else if (row_info->bit_depth == 16)
04352       {
04353          png_bytep rp;
04354          png_uint_32 i;
04355 
04356          if (row_info->color_type == PNG_COLOR_TYPE_RGB)
04357             bytes_per_pixel = 6;
04358 
04359          else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
04360             bytes_per_pixel = 8;
04361 
04362          else
04363             return;
04364 
04365          for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
04366          {
04367             png_uint_32 s0   = (*(rp    ) << 8) | *(rp + 1);
04368             png_uint_32 s1   = (*(rp + 2) << 8) | *(rp + 3);
04369             png_uint_32 s2   = (*(rp + 4) << 8) | *(rp + 5);
04370             png_uint_32 red  = (png_uint_32)((s0 + s1 + 65536L) & 0xffffL);
04371             png_uint_32 blue = (png_uint_32)((s2 + s1 + 65536L) & 0xffffL);
04372             *(rp  ) = (png_byte)((red >> 8) & 0xff);
04373             *(rp+1) = (png_byte)(red & 0xff);
04374             *(rp+4) = (png_byte)((blue >> 8) & 0xff);
04375             *(rp+5) = (png_byte)(blue & 0xff);
04376          }
04377       }
04378    }
04379 }
04380 #endif /* PNG_MNG_FEATURES_SUPPORTED */
04381 #endif /* PNG_READ_SUPPORTED */