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


openhrp3
Author(s): AIST, General Robotix Inc., Nakamura Lab of Dept. of Mechano Informatics at University of Tokyo
autogenerated on Sun Apr 2 2017 03:43:56