pngrtran.c

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

Generated on Tue Jul 5 14:13:31 2011 for ROOT_528-00b_version by  doxygen 1.5.1