Back to index

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