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

Generated on Fri Nov 28 00:06:22 2008 for elphel by  doxygen 1.5.1