ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

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.5.7 [December 15, 2011]
00005  * Copyright (c) 1998-2011 Glenn Randers-Pehrson
00006  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
00007  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
00008  *
00009  * This code is released under the libpng license.
00010  * For conditions of distribution and use, see the disclaimer
00011  * and license in png.h
00012  *
00013  * This file contains functions optionally called by an application
00014  * in order to tell libpng how to handle data when reading a PNG.
00015  * Transformations that are used in both reading and writing are
00016  * in pngtrans.c.
00017  */
00018 
00019 #include "pngpriv.h"
00020 
00021 #ifdef PNG_READ_SUPPORTED
00022 
00023 /* Set the action on getting a CRC error for an ancillary or critical chunk. */
00024 void PNGAPI
00025 png_set_crc_action(png_structp png_ptr, int crit_action, int ancil_action)
00026 {
00027    png_debug(1, "in png_set_crc_action");
00028 
00029    if (png_ptr == NULL)
00030       return;
00031 
00032    /* Tell libpng how we react to CRC errors in critical chunks */
00033    switch (crit_action)
00034    {
00035       case PNG_CRC_NO_CHANGE:                        /* Leave setting as is */
00036          break;
00037 
00038       case PNG_CRC_WARN_USE:                               /* Warn/use data */
00039          png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
00040          png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE;
00041          break;
00042 
00043       case PNG_CRC_QUIET_USE:                             /* Quiet/use data */
00044          png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
00045          png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE |
00046                            PNG_FLAG_CRC_CRITICAL_IGNORE;
00047          break;
00048 
00049       case PNG_CRC_WARN_DISCARD:    /* Not a valid action for critical data */
00050          png_warning(png_ptr,
00051             "Can't discard critical data on CRC error");
00052       case PNG_CRC_ERROR_QUIT:                                /* Error/quit */
00053 
00054       case PNG_CRC_DEFAULT:
00055       default:
00056          png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
00057          break;
00058    }
00059 
00060    /* Tell libpng how we react to CRC errors in ancillary chunks */
00061    switch (ancil_action)
00062    {
00063       case PNG_CRC_NO_CHANGE:                       /* Leave setting as is */
00064          break;
00065 
00066       case PNG_CRC_WARN_USE:                              /* Warn/use data */
00067          png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
00068          png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE;
00069          break;
00070 
00071       case PNG_CRC_QUIET_USE:                            /* Quiet/use data */
00072          png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
00073          png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE |
00074                            PNG_FLAG_CRC_ANCILLARY_NOWARN;
00075          break;
00076 
00077       case PNG_CRC_ERROR_QUIT:                               /* Error/quit */
00078          png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
00079          png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN;
00080          break;
00081 
00082       case PNG_CRC_WARN_DISCARD:                      /* Warn/discard data */
00083 
00084       case PNG_CRC_DEFAULT:
00085       default:
00086          png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
00087          break;
00088    }
00089 }
00090 
00091 #ifdef PNG_READ_BACKGROUND_SUPPORTED
00092 /* Handle alpha and tRNS via a background color */
00093 void PNGFAPI
00094 png_set_background_fixed(png_structp png_ptr,
00095     png_const_color_16p background_color, int background_gamma_code,
00096     int need_expand, png_fixed_point background_gamma)
00097 {
00098    png_debug(1, "in png_set_background_fixed");
00099 
00100    if (png_ptr == NULL)
00101       return;
00102 
00103    if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN)
00104    {
00105       png_warning(png_ptr, "Application must supply a known background gamma");
00106       return;
00107    }
00108 
00109    png_ptr->transformations |= PNG_COMPOSE | PNG_STRIP_ALPHA;
00110    png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
00111    png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
00112 
00113    png_memcpy(&(png_ptr->background), background_color,
00114       png_sizeof(png_color_16));
00115    png_ptr->background_gamma = background_gamma;
00116    png_ptr->background_gamma_type = (png_byte)(background_gamma_code);
00117    if (need_expand)
00118       png_ptr->transformations |= PNG_BACKGROUND_EXPAND;
00119    else
00120       png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND;
00121 }
00122 
00123 #  ifdef PNG_FLOATING_POINT_SUPPORTED
00124 void PNGAPI
00125 png_set_background(png_structp png_ptr,
00126     png_const_color_16p background_color, int background_gamma_code,
00127     int need_expand, double background_gamma)
00128 {
00129    png_set_background_fixed(png_ptr, background_color, background_gamma_code,
00130       need_expand, png_fixed(png_ptr, background_gamma, "png_set_background"));
00131 }
00132 #  endif  /* FLOATING_POINT */
00133 #endif /* READ_BACKGROUND */
00134 
00135 /* Scale 16-bit depth files to 8-bit depth.  If both of these are set then the
00136  * one that pngrtran does first (scale) happens.  This is necessary to allow the
00137  * TRANSFORM and API behavior to be somewhat consistent, and it's simpler.
00138  */
00139 #ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
00140 void PNGAPI
00141 png_set_scale_16(png_structp png_ptr)
00142 {
00143    png_debug(1, "in png_set_scale_16");
00144 
00145    if (png_ptr == NULL)
00146       return;
00147 
00148    png_ptr->transformations |= PNG_SCALE_16_TO_8;
00149 }
00150 #endif
00151 
00152 #ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
00153 /* Chop 16-bit depth files to 8-bit depth */
00154 void PNGAPI
00155 png_set_strip_16(png_structp png_ptr)
00156 {
00157    png_debug(1, "in png_set_strip_16");
00158 
00159    if (png_ptr == NULL)
00160       return;
00161 
00162    png_ptr->transformations |= PNG_16_TO_8;
00163 }
00164 #endif
00165 
00166 #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
00167 void PNGAPI
00168 png_set_strip_alpha(png_structp png_ptr)
00169 {
00170    png_debug(1, "in png_set_strip_alpha");
00171 
00172    if (png_ptr == NULL)
00173       return;
00174 
00175    png_ptr->transformations |= PNG_STRIP_ALPHA;
00176 }
00177 #endif
00178 
00179 #if defined(PNG_READ_ALPHA_MODE_SUPPORTED) || defined(PNG_READ_GAMMA_SUPPORTED)
00180 static png_fixed_point
00181 translate_gamma_flags(png_structp png_ptr, png_fixed_point output_gamma,
00182    int is_screen)
00183 {
00184    /* Check for flag values.  The main reason for having the old Mac value as a
00185     * flag is that it is pretty near impossible to work out what the correct
00186     * value is from Apple documentation - a working Mac system is needed to
00187     * discover the value!
00188     */
00189    if (output_gamma == PNG_DEFAULT_sRGB ||
00190       output_gamma == PNG_FP_1 / PNG_DEFAULT_sRGB)
00191    {
00192       /* If there is no sRGB support this just sets the gamma to the standard
00193        * sRGB value.  (This is a side effect of using this function!)
00194        */
00195 #     ifdef PNG_READ_sRGB_SUPPORTED
00196          png_ptr->flags |= PNG_FLAG_ASSUME_sRGB;
00197 #     endif
00198       if (is_screen)
00199          output_gamma = PNG_GAMMA_sRGB;
00200       else
00201          output_gamma = PNG_GAMMA_sRGB_INVERSE;
00202    }
00203 
00204    else if (output_gamma == PNG_GAMMA_MAC_18 ||
00205       output_gamma == PNG_FP_1 / PNG_GAMMA_MAC_18)
00206    {
00207       if (is_screen)
00208          output_gamma = PNG_GAMMA_MAC_OLD;
00209       else
00210          output_gamma = PNG_GAMMA_MAC_INVERSE;
00211    }
00212 
00213    return output_gamma;
00214 }
00215 
00216 #  ifdef PNG_FLOATING_POINT_SUPPORTED
00217 static png_fixed_point
00218 convert_gamma_value(png_structp png_ptr, double output_gamma)
00219 {
00220    /* The following silently ignores cases where fixed point (times 100,000)
00221     * gamma values are passed to the floating point API.  This is safe and it
00222     * means the fixed point constants work just fine with the floating point
00223     * API.  The alternative would just lead to undetected errors and spurious
00224     * bug reports.  Negative values fail inside the _fixed API unless they
00225     * correspond to the flag values.
00226     */
00227    if (output_gamma > 0 && output_gamma < 128)
00228       output_gamma *= PNG_FP_1;
00229 
00230    /* This preserves -1 and -2 exactly: */
00231    output_gamma = floor(output_gamma + .5);
00232 
00233    if (output_gamma > PNG_FP_MAX || output_gamma < PNG_FP_MIN)
00234       png_fixed_error(png_ptr, "gamma value");
00235 
00236    return (png_fixed_point)output_gamma;
00237 }
00238 #  endif
00239 #endif /* READ_ALPHA_MODE || READ_GAMMA */
00240 
00241 #ifdef PNG_READ_ALPHA_MODE_SUPPORTED
00242 void PNGFAPI
00243 png_set_alpha_mode_fixed(png_structp png_ptr, int mode,
00244    png_fixed_point output_gamma)
00245 {
00246    int compose = 0;
00247    png_fixed_point file_gamma;
00248 
00249    png_debug(1, "in png_set_alpha_mode");
00250 
00251    if (png_ptr == NULL)
00252       return;
00253 
00254    output_gamma = translate_gamma_flags(png_ptr, output_gamma, 1/*screen*/);
00255 
00256    /* Validate the value to ensure it is in a reasonable range. The value
00257     * is expected to be 1 or greater, but this range test allows for some
00258     * viewing correction values.  The intent is to weed out users of this API
00259     * who use the inverse of the gamma value accidentally!  Since some of these
00260     * values are reasonable this may have to be changed.
00261     */
00262    if (output_gamma < 70000 || output_gamma > 300000)
00263       png_error(png_ptr, "output gamma out of expected range");
00264 
00265    /* The default file gamma is the inverse of the output gamma; the output
00266     * gamma may be changed below so get the file value first:
00267     */
00268    file_gamma = png_reciprocal(output_gamma);
00269 
00270    /* There are really 8 possibilities here, composed of any combination
00271     * of:
00272     *
00273     *    premultiply the color channels
00274     *    do not encode non-opaque pixels
00275     *    encode the alpha as well as the color channels
00276     *
00277     * The differences disappear if the input/output ('screen') gamma is 1.0,
00278     * because then the encoding is a no-op and there is only the choice of
00279     * premultiplying the color channels or not.
00280     *
00281     * png_set_alpha_mode and png_set_background interact because both use
00282     * png_compose to do the work.  Calling both is only useful when
00283     * png_set_alpha_mode is used to set the default mode - PNG_ALPHA_PNG - along
00284     * with a default gamma value.  Otherwise PNG_COMPOSE must not be set.
00285     */
00286    switch (mode)
00287    {
00288       case PNG_ALPHA_PNG:        /* default: png standard */
00289          /* No compose, but it may be set by png_set_background! */
00290          png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
00291          png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
00292          break;
00293 
00294       case PNG_ALPHA_ASSOCIATED: /* color channels premultiplied */
00295          compose = 1;
00296          png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
00297          png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
00298          /* The output is linear: */
00299          output_gamma = PNG_FP_1;
00300          break;
00301 
00302       case PNG_ALPHA_OPTIMIZED:  /* associated, non-opaque pixels linear */
00303          compose = 1;
00304          png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
00305          png_ptr->flags |= PNG_FLAG_OPTIMIZE_ALPHA;
00306          /* output_gamma records the encoding of opaque pixels! */
00307          break;
00308 
00309       case PNG_ALPHA_BROKEN:     /* associated, non-linear, alpha encoded */
00310          compose = 1;
00311          png_ptr->transformations |= PNG_ENCODE_ALPHA;
00312          png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
00313          break;
00314 
00315       default:
00316          png_error(png_ptr, "invalid alpha mode");
00317    }
00318 
00319    /* Only set the default gamma if the file gamma has not been set (this has
00320     * the side effect that the gamma in a second call to png_set_alpha_mode will
00321     * be ignored.)
00322     */
00323    if (png_ptr->gamma == 0)
00324       png_ptr->gamma = file_gamma;
00325 
00326    /* But always set the output gamma: */
00327    png_ptr->screen_gamma = output_gamma;
00328 
00329    /* Finally, if pre-multiplying, set the background fields to achieve the
00330     * desired result.
00331     */
00332    if (compose)
00333    {
00334       /* And obtain alpha pre-multiplication by composing on black: */
00335       png_memset(&png_ptr->background, 0, sizeof png_ptr->background);
00336       png_ptr->background_gamma = png_ptr->gamma; /* just in case */
00337       png_ptr->background_gamma_type = PNG_BACKGROUND_GAMMA_FILE;
00338       png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND;
00339 
00340       if (png_ptr->transformations & PNG_COMPOSE)
00341          png_error(png_ptr,
00342             "conflicting calls to set alpha mode and background");
00343 
00344       png_ptr->transformations |= PNG_COMPOSE;
00345    }
00346 
00347    /* New API, make sure apps call the correct initializers: */
00348    png_ptr->flags |= PNG_FLAG_DETECT_UNINITIALIZED;
00349 }
00350 
00351 #  ifdef PNG_FLOATING_POINT_SUPPORTED
00352 void PNGAPI
00353 png_set_alpha_mode(png_structp png_ptr, int mode, double output_gamma)
00354 {
00355    png_set_alpha_mode_fixed(png_ptr, mode, convert_gamma_value(png_ptr,
00356       output_gamma));
00357 }
00358 #  endif
00359 #endif
00360 
00361 #ifdef PNG_READ_QUANTIZE_SUPPORTED
00362 /* Dither file to 8-bit.  Supply a palette, the current number
00363  * of elements in the palette, the maximum number of elements
00364  * allowed, and a histogram if possible.  If the current number
00365  * of colors is greater then the maximum number, the palette will be
00366  * modified to fit in the maximum number.  "full_quantize" indicates
00367  * whether we need a quantizing cube set up for RGB images, or if we
00368  * simply are reducing the number of colors in a paletted image.
00369  */
00370 
00371 typedef struct png_dsort_struct
00372 {
00373    struct png_dsort_struct FAR * next;
00374    png_byte left;
00375    png_byte right;
00376 } png_dsort;
00377 typedef png_dsort FAR *       png_dsortp;
00378 typedef png_dsort FAR * FAR * png_dsortpp;
00379 
00380 void PNGAPI
00381 png_set_quantize(png_structp png_ptr, png_colorp palette,
00382     int num_palette, int maximum_colors, png_const_uint_16p histogram,
00383     int full_quantize)
00384 {
00385    png_debug(1, "in png_set_quantize");
00386 
00387    if (png_ptr == NULL)
00388       return;
00389 
00390    png_ptr->transformations |= PNG_QUANTIZE;
00391 
00392    if (!full_quantize)
00393    {
00394       int i;
00395 
00396       png_ptr->quantize_index = (png_bytep)png_malloc(png_ptr,
00397           (png_uint_32)(num_palette * png_sizeof(png_byte)));
00398       for (i = 0; i < num_palette; i++)
00399          png_ptr->quantize_index[i] = (png_byte)i;
00400    }
00401 
00402    if (num_palette > maximum_colors)
00403    {
00404       if (histogram != NULL)
00405       {
00406          /* This is easy enough, just throw out the least used colors.
00407           * Perhaps not the best solution, but good enough.
00408           */
00409 
00410          int i;
00411 
00412          /* Initialize an array to sort colors */
00413          png_ptr->quantize_sort = (png_bytep)png_malloc(png_ptr,
00414              (png_uint_32)(num_palette * png_sizeof(png_byte)));
00415 
00416          /* Initialize the quantize_sort array */
00417          for (i = 0; i < num_palette; i++)
00418             png_ptr->quantize_sort[i] = (png_byte)i;
00419 
00420          /* Find the least used palette entries by starting a
00421           * bubble sort, and running it until we have sorted
00422           * out enough colors.  Note that we don't care about
00423           * sorting all the colors, just finding which are
00424           * least used.
00425           */
00426 
00427          for (i = num_palette - 1; i >= maximum_colors; i--)
00428          {
00429             int done; /* To stop early if the list is pre-sorted */
00430             int j;
00431 
00432             done = 1;
00433             for (j = 0; j < i; j++)
00434             {
00435                if (histogram[png_ptr->quantize_sort[j]]
00436                    < histogram[png_ptr->quantize_sort[j + 1]])
00437                {
00438                   png_byte t;
00439 
00440                   t = png_ptr->quantize_sort[j];
00441                   png_ptr->quantize_sort[j] = png_ptr->quantize_sort[j + 1];
00442                   png_ptr->quantize_sort[j + 1] = t;
00443                   done = 0;
00444                }
00445             }
00446 
00447             if (done)
00448                break;
00449          }
00450 
00451          /* Swap the palette around, and set up a table, if necessary */
00452          if (full_quantize)
00453          {
00454             int j = num_palette;
00455 
00456             /* Put all the useful colors within the max, but don't
00457              * move the others.
00458              */
00459             for (i = 0; i < maximum_colors; i++)
00460             {
00461                if ((int)png_ptr->quantize_sort[i] >= maximum_colors)
00462                {
00463                   do
00464                      j--;
00465                   while ((int)png_ptr->quantize_sort[j] >= maximum_colors);
00466 
00467                   palette[i] = palette[j];
00468                }
00469             }
00470          }
00471          else
00472          {
00473             int j = num_palette;
00474 
00475             /* Move all the used colors inside the max limit, and
00476              * develop a translation table.
00477              */
00478             for (i = 0; i < maximum_colors; i++)
00479             {
00480                /* Only move the colors we need to */
00481                if ((int)png_ptr->quantize_sort[i] >= maximum_colors)
00482                {
00483                   png_color tmp_color;
00484 
00485                   do
00486                      j--;
00487                   while ((int)png_ptr->quantize_sort[j] >= maximum_colors);
00488 
00489                   tmp_color = palette[j];
00490                   palette[j] = palette[i];
00491                   palette[i] = tmp_color;
00492                   /* Indicate where the color went */
00493                   png_ptr->quantize_index[j] = (png_byte)i;
00494                   png_ptr->quantize_index[i] = (png_byte)j;
00495                }
00496             }
00497 
00498             /* Find closest color for those colors we are not using */
00499             for (i = 0; i < num_palette; i++)
00500             {
00501                if ((int)png_ptr->quantize_index[i] >= maximum_colors)
00502                {
00503                   int min_d, k, min_k, d_index;
00504 
00505                   /* Find the closest color to one we threw out */
00506                   d_index = png_ptr->quantize_index[i];
00507                   min_d = PNG_COLOR_DIST(palette[d_index], palette[0]);
00508                   for (k = 1, min_k = 0; k < maximum_colors; k++)
00509                   {
00510                      int d;
00511 
00512                      d = PNG_COLOR_DIST(palette[d_index], palette[k]);
00513 
00514                      if (d < min_d)
00515                      {
00516                         min_d = d;
00517                         min_k = k;
00518                      }
00519                   }
00520                   /* Point to closest color */
00521                   png_ptr->quantize_index[i] = (png_byte)min_k;
00522                }
00523             }
00524          }
00525          png_free(png_ptr, png_ptr->quantize_sort);
00526          png_ptr->quantize_sort = NULL;
00527       }
00528       else
00529       {
00530          /* This is much harder to do simply (and quickly).  Perhaps
00531           * we need to go through a median cut routine, but those
00532           * don't always behave themselves with only a few colors
00533           * as input.  So we will just find the closest two colors,
00534           * and throw out one of them (chosen somewhat randomly).
00535           * [We don't understand this at all, so if someone wants to
00536           *  work on improving it, be our guest - AED, GRP]
00537           */
00538          int i;
00539          int max_d;
00540          int num_new_palette;
00541          png_dsortp t;
00542          png_dsortpp hash;
00543 
00544          t = NULL;
00545 
00546          /* Initialize palette index arrays */
00547          png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr,
00548              (png_uint_32)(num_palette * png_sizeof(png_byte)));
00549          png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr,
00550              (png_uint_32)(num_palette * png_sizeof(png_byte)));
00551 
00552          /* Initialize the sort array */
00553          for (i = 0; i < num_palette; i++)
00554          {
00555             png_ptr->index_to_palette[i] = (png_byte)i;
00556             png_ptr->palette_to_index[i] = (png_byte)i;
00557          }
00558 
00559          hash = (png_dsortpp)png_calloc(png_ptr, (png_uint_32)(769 *
00560              png_sizeof(png_dsortp)));
00561 
00562          num_new_palette = num_palette;
00563 
00564          /* Initial wild guess at how far apart the farthest pixel
00565           * pair we will be eliminating will be.  Larger
00566           * numbers mean more areas will be allocated, Smaller
00567           * numbers run the risk of not saving enough data, and
00568           * having to do this all over again.
00569           *
00570           * I have not done extensive checking on this number.
00571           */
00572          max_d = 96;
00573 
00574          while (num_new_palette > maximum_colors)
00575          {
00576             for (i = 0; i < num_new_palette - 1; i++)
00577             {
00578                int j;
00579 
00580                for (j = i + 1; j < num_new_palette; j++)
00581                {
00582                   int d;
00583 
00584                   d = PNG_COLOR_DIST(palette[i], palette[j]);
00585 
00586                   if (d <= max_d)
00587                   {
00588 
00589                      t = (png_dsortp)png_malloc_warn(png_ptr,
00590                          (png_uint_32)(png_sizeof(png_dsort)));
00591 
00592                      if (t == NULL)
00593                          break;
00594 
00595                      t->next = hash[d];
00596                      t->left = (png_byte)i;
00597                      t->right = (png_byte)j;
00598                      hash[d] = t;
00599                   }
00600                }
00601                if (t == NULL)
00602                   break;
00603             }
00604 
00605             if (t != NULL)
00606             for (i = 0; i <= max_d; i++)
00607             {
00608                if (hash[i] != NULL)
00609                {
00610                   png_dsortp p;
00611 
00612                   for (p = hash[i]; p; p = p->next)
00613                   {
00614                      if ((int)png_ptr->index_to_palette[p->left]
00615                          < num_new_palette &&
00616                          (int)png_ptr->index_to_palette[p->right]
00617                          < num_new_palette)
00618                      {
00619                         int j, next_j;
00620 
00621                         if (num_new_palette & 0x01)
00622                         {
00623                            j = p->left;
00624                            next_j = p->right;
00625                         }
00626                         else
00627                         {
00628                            j = p->right;
00629                            next_j = p->left;
00630                         }
00631 
00632                         num_new_palette--;
00633                         palette[png_ptr->index_to_palette[j]]
00634                             = palette[num_new_palette];
00635                         if (!full_quantize)
00636                         {
00637                            int k;
00638 
00639                            for (k = 0; k < num_palette; k++)
00640                            {
00641                               if (png_ptr->quantize_index[k] ==
00642                                   png_ptr->index_to_palette[j])
00643                                  png_ptr->quantize_index[k] =
00644                                      png_ptr->index_to_palette[next_j];
00645 
00646                               if ((int)png_ptr->quantize_index[k] ==
00647                                   num_new_palette)
00648                                  png_ptr->quantize_index[k] =
00649                                      png_ptr->index_to_palette[j];
00650                            }
00651                         }
00652 
00653                         png_ptr->index_to_palette[png_ptr->palette_to_index
00654                             [num_new_palette]] = png_ptr->index_to_palette[j];
00655 
00656                         png_ptr->palette_to_index[png_ptr->index_to_palette[j]]
00657                             = png_ptr->palette_to_index[num_new_palette];
00658 
00659                         png_ptr->index_to_palette[j] =
00660                             (png_byte)num_new_palette;
00661 
00662                         png_ptr->palette_to_index[num_new_palette] =
00663                             (png_byte)j;
00664                      }
00665                      if (num_new_palette <= maximum_colors)
00666                         break;
00667                   }
00668                   if (num_new_palette <= maximum_colors)
00669                      break;
00670                }
00671             }
00672 
00673             for (i = 0; i < 769; i++)
00674             {
00675                if (hash[i] != NULL)
00676                {
00677                   png_dsortp p = hash[i];
00678                   while (p)
00679                   {
00680                      t = p->next;
00681                      png_free(png_ptr, p);
00682                      p = t;
00683                   }
00684                }
00685                hash[i] = 0;
00686             }
00687             max_d += 96;
00688          }
00689          png_free(png_ptr, hash);
00690          png_free(png_ptr, png_ptr->palette_to_index);
00691          png_free(png_ptr, png_ptr->index_to_palette);
00692          png_ptr->palette_to_index = NULL;
00693          png_ptr->index_to_palette = NULL;
00694       }
00695       num_palette = maximum_colors;
00696    }
00697    if (png_ptr->palette == NULL)
00698    {
00699       png_ptr->palette = palette;
00700    }
00701    png_ptr->num_palette = (png_uint_16)num_palette;
00702 
00703    if (full_quantize)
00704    {
00705       int i;
00706       png_bytep distance;
00707       int total_bits = PNG_QUANTIZE_RED_BITS + PNG_QUANTIZE_GREEN_BITS +
00708           PNG_QUANTIZE_BLUE_BITS;
00709       int num_red = (1 << PNG_QUANTIZE_RED_BITS);
00710       int num_green = (1 << PNG_QUANTIZE_GREEN_BITS);
00711       int num_blue = (1 << PNG_QUANTIZE_BLUE_BITS);
00712       png_size_t num_entries = ((png_size_t)1 << total_bits);
00713 
00714       png_ptr->palette_lookup = (png_bytep)png_calloc(png_ptr,
00715           (png_uint_32)(num_entries * png_sizeof(png_byte)));
00716 
00717       distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries *
00718           png_sizeof(png_byte)));
00719 
00720       png_memset(distance, 0xff, num_entries * png_sizeof(png_byte));
00721 
00722       for (i = 0; i < num_palette; i++)
00723       {
00724          int ir, ig, ib;
00725          int r = (palette[i].red >> (8 - PNG_QUANTIZE_RED_BITS));
00726          int g = (palette[i].green >> (8 - PNG_QUANTIZE_GREEN_BITS));
00727          int b = (palette[i].blue >> (8 - PNG_QUANTIZE_BLUE_BITS));
00728 
00729          for (ir = 0; ir < num_red; ir++)
00730          {
00731             /* int dr = abs(ir - r); */
00732             int dr = ((ir > r) ? ir - r : r - ir);
00733             int index_r = (ir << (PNG_QUANTIZE_BLUE_BITS +
00734                 PNG_QUANTIZE_GREEN_BITS));
00735 
00736             for (ig = 0; ig < num_green; ig++)
00737             {
00738                /* int dg = abs(ig - g); */
00739                int dg = ((ig > g) ? ig - g : g - ig);
00740                int dt = dr + dg;
00741                int dm = ((dr > dg) ? dr : dg);
00742                int index_g = index_r | (ig << PNG_QUANTIZE_BLUE_BITS);
00743 
00744                for (ib = 0; ib < num_blue; ib++)
00745                {
00746                   int d_index = index_g | ib;
00747                   /* int db = abs(ib - b); */
00748                   int db = ((ib > b) ? ib - b : b - ib);
00749                   int dmax = ((dm > db) ? dm : db);
00750                   int d = dmax + dt + db;
00751 
00752                   if (d < (int)distance[d_index])
00753                   {
00754                      distance[d_index] = (png_byte)d;
00755                      png_ptr->palette_lookup[d_index] = (png_byte)i;
00756                   }
00757                }
00758             }
00759          }
00760       }
00761 
00762       png_free(png_ptr, distance);
00763    }
00764 }
00765 #endif /* PNG_READ_QUANTIZE_SUPPORTED */
00766 
00767 #ifdef PNG_READ_GAMMA_SUPPORTED
00768 void PNGFAPI
00769 png_set_gamma_fixed(png_structp png_ptr, png_fixed_point scrn_gamma,
00770    png_fixed_point file_gamma)
00771 {
00772    png_debug(1, "in png_set_gamma_fixed");
00773 
00774    if (png_ptr == NULL)
00775       return;
00776 
00777    /* New in libpng-1.5.4 - reserve particular negative values as flags. */
00778    scrn_gamma = translate_gamma_flags(png_ptr, scrn_gamma, 1/*screen*/);
00779    file_gamma = translate_gamma_flags(png_ptr, file_gamma, 0/*file*/);
00780 
00781 #if PNG_LIBPNG_VER >= 10600
00782    /* Checking the gamma values for being >0 was added in 1.5.4 along with the
00783     * premultiplied alpha support; this actually hides an undocumented feature
00784     * of the previous implementation which allowed gamma processing to be
00785     * disabled in background handling.  There is no evidence (so far) that this
00786     * was being used; however, png_set_background itself accepted and must still
00787     * accept '0' for the gamma value it takes, because it isn't always used.
00788     *
00789     * Since this is an API change (albeit a very minor one that removes an
00790     * undocumented API feature) it will not be made until libpng-1.6.0.
00791     */
00792    if (file_gamma <= 0)
00793       png_error(png_ptr, "invalid file gamma in png_set_gamma");
00794 
00795    if (scrn_gamma <= 0)
00796       png_error(png_ptr, "invalid screen gamma in png_set_gamma");
00797 #endif
00798 
00799    /* Set the gamma values unconditionally - this overrides the value in the PNG
00800     * file if a gAMA chunk was present.  png_set_alpha_mode provides a
00801     * different, easier, way to default the file gamma.
00802     */
00803    png_ptr->gamma = file_gamma;
00804    png_ptr->screen_gamma = scrn_gamma;
00805 }
00806 
00807 #  ifdef PNG_FLOATING_POINT_SUPPORTED
00808 void PNGAPI
00809 png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma)
00810 {
00811    png_set_gamma_fixed(png_ptr, convert_gamma_value(png_ptr, scrn_gamma),
00812       convert_gamma_value(png_ptr, file_gamma));
00813 }
00814 #  endif /* FLOATING_POINT_SUPPORTED */
00815 #endif /* READ_GAMMA */
00816 
00817 #ifdef PNG_READ_EXPAND_SUPPORTED
00818 /* Expand paletted images to RGB, expand grayscale images of
00819  * less than 8-bit depth to 8-bit depth, and expand tRNS chunks
00820  * to alpha channels.
00821  */
00822 void PNGAPI
00823 png_set_expand(png_structp png_ptr)
00824 {
00825    png_debug(1, "in png_set_expand");
00826 
00827    if (png_ptr == NULL)
00828       return;
00829 
00830    png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
00831    png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
00832 }
00833 
00834 /* GRR 19990627:  the following three functions currently are identical
00835  *  to png_set_expand().  However, it is entirely reasonable that someone
00836  *  might wish to expand an indexed image to RGB but *not* expand a single,
00837  *  fully transparent palette entry to a full alpha channel--perhaps instead
00838  *  convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace
00839  *  the transparent color with a particular RGB value, or drop tRNS entirely.
00840  *  IOW, a future version of the library may make the transformations flag
00841  *  a bit more fine-grained, with separate bits for each of these three
00842  *  functions.
00843  *
00844  *  More to the point, these functions make it obvious what libpng will be
00845  *  doing, whereas "expand" can (and does) mean any number of things.
00846  *
00847  *  GRP 20060307: In libpng-1.2.9, png_set_gray_1_2_4_to_8() was modified
00848  *  to expand only the sample depth but not to expand the tRNS to alpha
00849  *  and its name was changed to png_set_expand_gray_1_2_4_to_8().
00850  */
00851 
00852 /* Expand paletted images to RGB. */
00853 void PNGAPI
00854 png_set_palette_to_rgb(png_structp png_ptr)
00855 {
00856    png_debug(1, "in png_set_palette_to_rgb");
00857 
00858    if (png_ptr == NULL)
00859       return;
00860 
00861    png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
00862    png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
00863 }
00864 
00865 /* Expand grayscale images of less than 8-bit depth to 8 bits. */
00866 void PNGAPI
00867 png_set_expand_gray_1_2_4_to_8(png_structp png_ptr)
00868 {
00869    png_debug(1, "in png_set_expand_gray_1_2_4_to_8");
00870 
00871    if (png_ptr == NULL)
00872       return;
00873 
00874    png_ptr->transformations |= PNG_EXPAND;
00875    png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
00876 }
00877 
00878 
00879 
00880 /* Expand tRNS chunks to alpha channels. */
00881 void PNGAPI
00882 png_set_tRNS_to_alpha(png_structp png_ptr)
00883 {
00884    png_debug(1, "in png_set_tRNS_to_alpha");
00885 
00886    png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
00887    png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
00888 }
00889 #endif /* defined(PNG_READ_EXPAND_SUPPORTED) */
00890 
00891 #ifdef PNG_READ_EXPAND_16_SUPPORTED
00892 /* Expand to 16-bit channels, expand the tRNS chunk too (because otherwise
00893  * it may not work correctly.)
00894  */
00895 void PNGAPI
00896 png_set_expand_16(png_structp png_ptr)
00897 {
00898    png_debug(1, "in png_set_expand_16");
00899 
00900    if (png_ptr == NULL)
00901       return;
00902 
00903    png_ptr->transformations |= (PNG_EXPAND_16 | PNG_EXPAND | PNG_EXPAND_tRNS);
00904    png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
00905 
00906    /* New API, make sure apps call the correct initializers: */
00907    png_ptr->flags |= PNG_FLAG_DETECT_UNINITIALIZED;
00908 }
00909 #endif
00910 
00911 #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
00912 void PNGAPI
00913 png_set_gray_to_rgb(png_structp png_ptr)
00914 {
00915    png_debug(1, "in png_set_gray_to_rgb");
00916 
00917    if (png_ptr != NULL)
00918    {
00919       /* Because rgb must be 8 bits or more: */
00920       png_set_expand_gray_1_2_4_to_8(png_ptr);
00921       png_ptr->transformations |= PNG_GRAY_TO_RGB;
00922       png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
00923    }
00924 }
00925 #endif
00926 
00927 #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
00928 void PNGFAPI
00929 png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action,
00930     png_fixed_point red, png_fixed_point green)
00931 {
00932    png_debug(1, "in png_set_rgb_to_gray");
00933 
00934    if (png_ptr == NULL)
00935       return;
00936 
00937    switch(error_action)
00938    {
00939       case PNG_ERROR_ACTION_NONE:
00940          png_ptr->transformations |= PNG_RGB_TO_GRAY;
00941          break;
00942 
00943       case PNG_ERROR_ACTION_WARN:
00944          png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN;
00945          break;
00946 
00947       case PNG_ERROR_ACTION_ERROR:
00948          png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR;
00949          break;
00950 
00951       default:
00952          png_error(png_ptr, "invalid error action to rgb_to_gray");
00953          break;
00954    }
00955    if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
00956 #ifdef PNG_READ_EXPAND_SUPPORTED
00957       png_ptr->transformations |= PNG_EXPAND;
00958 #else
00959    {
00960       png_warning(png_ptr,
00961         "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED");
00962 
00963       png_ptr->transformations &= ~PNG_RGB_TO_GRAY;
00964    }
00965 #endif
00966    {
00967       if (red >= 0 && green >= 0 && red + green <= PNG_FP_1)
00968       {
00969          png_uint_16 red_int, green_int;
00970 
00971          /* NOTE: this calculation does not round, but this behavior is retained
00972           * for consistency, the inaccuracy is very small.  The code here always
00973           * overwrites the coefficients, regardless of whether they have been
00974           * defaulted or set already.
00975           */
00976          red_int = (png_uint_16)(((png_uint_32)red*32768)/100000);
00977          green_int = (png_uint_16)(((png_uint_32)green*32768)/100000);
00978 
00979          png_ptr->rgb_to_gray_red_coeff   = red_int;
00980          png_ptr->rgb_to_gray_green_coeff = green_int;
00981          png_ptr->rgb_to_gray_coefficients_set = 1;
00982       }
00983 
00984       else
00985       {
00986          if (red >= 0 && green >= 0)
00987             png_warning(png_ptr,
00988                "ignoring out of range rgb_to_gray coefficients");
00989 
00990          /* Use the defaults, from the cHRM chunk if set, else the historical
00991           * values which are close to the sRGB/HDTV/ITU-Rec 709 values.  See
00992           * png_do_rgb_to_gray for more discussion of the values.  In this case
00993           * the coefficients are not marked as 'set' and are not overwritten if
00994           * something has already provided a default.
00995           */
00996          if (png_ptr->rgb_to_gray_red_coeff == 0 &&
00997             png_ptr->rgb_to_gray_green_coeff == 0)
00998          {
00999             png_ptr->rgb_to_gray_red_coeff   = 6968;
01000             png_ptr->rgb_to_gray_green_coeff = 23434;
01001             /* png_ptr->rgb_to_gray_blue_coeff  = 2366; */
01002          }
01003       }
01004    }
01005 }
01006 
01007 #ifdef PNG_FLOATING_POINT_SUPPORTED
01008 /* Convert a RGB image to a grayscale of the same width.  This allows us,
01009  * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image.
01010  */
01011 
01012 void PNGAPI
01013 png_set_rgb_to_gray(png_structp png_ptr, int error_action, double red,
01014    double green)
01015 {
01016    if (png_ptr == NULL)
01017       return;
01018 
01019    png_set_rgb_to_gray_fixed(png_ptr, error_action,
01020       png_fixed(png_ptr, red, "rgb to gray red coefficient"),
01021       png_fixed(png_ptr, green, "rgb to gray green coefficient"));
01022 }
01023 #endif /* FLOATING POINT */
01024 
01025 #endif
01026 
01027 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
01028     defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
01029 void PNGAPI
01030 png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr
01031     read_user_transform_fn)
01032 {
01033    png_debug(1, "in png_set_read_user_transform_fn");
01034 
01035    if (png_ptr == NULL)
01036       return;
01037 
01038 #ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
01039    png_ptr->transformations |= PNG_USER_TRANSFORM;
01040    png_ptr->read_user_transform_fn = read_user_transform_fn;
01041 #endif
01042 }
01043 #endif
01044 
01045 #ifdef PNG_READ_TRANSFORMS_SUPPORTED
01046 #ifdef PNG_READ_GAMMA_SUPPORTED
01047 /* In the case of gamma transformations only do transformations on images where
01048  * the [file] gamma and screen_gamma are not close reciprocals, otherwise it
01049  * slows things down slightly, and also needlessly introduces small errors.
01050  */
01051 static int /* PRIVATE */
01052 png_gamma_threshold(png_fixed_point screen_gamma, png_fixed_point file_gamma)
01053 {
01054    /* PNG_GAMMA_THRESHOLD is the threshold for performing gamma
01055     * correction as a difference of the overall transform from 1.0
01056     *
01057     * We want to compare the threshold with s*f - 1, if we get
01058     * overflow here it is because of wacky gamma values so we
01059     * turn on processing anyway.
01060     */
01061    png_fixed_point gtest;
01062    return !png_muldiv(&gtest, screen_gamma, file_gamma, PNG_FP_1) ||
01063        png_gamma_significant(gtest);
01064 }
01065 #endif
01066 
01067 /* Initialize everything needed for the read.  This includes modifying
01068  * the palette.
01069  */
01070 
01071 /*For the moment 'png_init_palette_transformations' and
01072  * 'png_init_rgb_transformations' only do some flag canceling optimizations.
01073  * The intent is that these two routines should have palette or rgb operations
01074  * extracted from 'png_init_read_transformations'.
01075  */
01076 static void /* PRIVATE */
01077 png_init_palette_transformations(png_structp png_ptr)
01078 {
01079    /* Called to handle the (input) palette case.  In png_do_read_transformations
01080     * the first step is to expand the palette if requested, so this code must
01081     * take care to only make changes that are invariant with respect to the
01082     * palette expansion, or only do them if there is no expansion.
01083     *
01084     * STRIP_ALPHA has already been handled in the caller (by setting num_trans
01085     * to 0.)
01086     */
01087    int input_has_alpha = 0;
01088    int input_has_transparency = 0;
01089 
01090    if (png_ptr->num_trans > 0)
01091    {
01092       int i;
01093 
01094       /* Ignore if all the entries are opaque (unlikely!) */
01095       for (i=0; i<png_ptr->num_trans; ++i)
01096          if (png_ptr->trans_alpha[i] == 255)
01097             continue;
01098          else if (png_ptr->trans_alpha[i] == 0)
01099             input_has_transparency = 1;
01100          else
01101             input_has_alpha = 1;
01102    }
01103 
01104    /* If no alpha we can optimize. */
01105    if (!input_has_alpha)
01106    {
01107       /* Any alpha means background and associative alpha processing is
01108        * required, however if the alpha is 0 or 1 throughout OPTIIMIZE_ALPHA
01109        * and ENCODE_ALPHA are irrelevant.
01110        */
01111       png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
01112       png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
01113 
01114       if (!input_has_transparency)
01115          png_ptr->transformations &= ~(PNG_COMPOSE | PNG_BACKGROUND_EXPAND);
01116    }
01117 
01118 #if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
01119    /* png_set_background handling - deals with the complexity of whether the
01120     * background color is in the file format or the screen format in the case
01121     * where an 'expand' will happen.
01122     */
01123 
01124    /* The following code cannot be entered in the alpha pre-multiplication case
01125     * because PNG_BACKGROUND_EXPAND is cancelled below.
01126     */
01127    if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
01128        (png_ptr->transformations & PNG_EXPAND))
01129    {
01130       {
01131          png_ptr->background.red   =
01132              png_ptr->palette[png_ptr->background.index].red;
01133          png_ptr->background.green =
01134              png_ptr->palette[png_ptr->background.index].green;
01135          png_ptr->background.blue  =
01136              png_ptr->palette[png_ptr->background.index].blue;
01137 
01138 #ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
01139         if (png_ptr->transformations & PNG_INVERT_ALPHA)
01140         {
01141            if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
01142            {
01143               /* Invert the alpha channel (in tRNS) unless the pixels are
01144                * going to be expanded, in which case leave it for later
01145                */
01146               int i, istop = png_ptr->num_trans;
01147 
01148               for (i=0; i<istop; i++)
01149                  png_ptr->trans_alpha[i] = (png_byte)(255 -
01150                     png_ptr->trans_alpha[i]);
01151            }
01152         }
01153 #endif /* PNG_READ_INVERT_ALPHA_SUPPORTED */
01154       }
01155    } /* background expand and (therefore) no alpha association. */
01156 #endif /* PNG_READ_EXPAND_SUPPORTED && PNG_READ_BACKGROUND_SUPPORTED */
01157 }
01158 
01159 static void /* PRIVATE */
01160 png_init_rgb_transformations(png_structp png_ptr)
01161 {
01162    /* Added to libpng-1.5.4: check the color type to determine whether there
01163     * is any alpha or transparency in the image and simply cancel the
01164     * background and alpha mode stuff if there isn't.
01165     */
01166    int input_has_alpha = (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0;
01167    int input_has_transparency = png_ptr->num_trans > 0;
01168 
01169    /* If no alpha we can optimize. */
01170    if (!input_has_alpha)
01171    {
01172       /* Any alpha means background and associative alpha processing is
01173        * required, however if the alpha is 0 or 1 throughout OPTIIMIZE_ALPHA
01174        * and ENCODE_ALPHA are irrelevant.
01175        */
01176 #     ifdef PNG_READ_ALPHA_MODE_SUPPORTED
01177          png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
01178          png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
01179 #     endif
01180 
01181       if (!input_has_transparency)
01182          png_ptr->transformations &= ~(PNG_COMPOSE | PNG_BACKGROUND_EXPAND);
01183    }
01184 
01185 #if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
01186    /* png_set_background handling - deals with the complexity of whether the
01187     * background color is in the file format or the screen format in the case
01188     * where an 'expand' will happen.
01189     */
01190 
01191    /* The following code cannot be entered in the alpha pre-multiplication case
01192     * because PNG_BACKGROUND_EXPAND is cancelled below.
01193     */
01194    if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
01195        (png_ptr->transformations & PNG_EXPAND) &&
01196        !(png_ptr->color_type & PNG_COLOR_MASK_COLOR))
01197        /* i.e., GRAY or GRAY_ALPHA */
01198    {
01199       {
01200          /* Expand background and tRNS chunks */
01201          int gray = png_ptr->background.gray;
01202          int trans_gray = png_ptr->trans_color.gray;
01203 
01204          switch (png_ptr->bit_depth)
01205          {
01206             case 1:
01207                gray *= 0xff;
01208                trans_gray *= 0xff;
01209                break;
01210 
01211             case 2:
01212                gray *= 0x55;
01213                trans_gray *= 0x55;
01214                break;
01215 
01216             case 4:
01217                gray *= 0x11;
01218                trans_gray *= 0x11;
01219                break;
01220 
01221             default:
01222 
01223             case 8:
01224                /* Already 8 bits, fall through */
01225 
01226             case 16:
01227                /* Already a full 16 bits */
01228                break;
01229          }
01230 
01231          png_ptr->background.red = png_ptr->background.green =
01232             png_ptr->background.blue = (png_uint_16)gray;
01233 
01234          if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
01235          {
01236             png_ptr->trans_color.red = png_ptr->trans_color.green =
01237                png_ptr->trans_color.blue = (png_uint_16)trans_gray;
01238          }
01239       }
01240    } /* background expand and (therefore) no alpha association. */
01241 #endif /* PNG_READ_EXPAND_SUPPORTED && PNG_READ_BACKGROUND_SUPPORTED */
01242 }
01243 
01244 void /* PRIVATE */
01245 png_init_read_transformations(png_structp png_ptr)
01246 {
01247    png_debug(1, "in png_init_read_transformations");
01248 
01249    /* This internal function is called from png_read_start_row in pngrutil.c
01250     * and it is called before the 'rowbytes' calculation is done, so the code
01251     * in here can change or update the transformations flags.
01252     *
01253     * First do updates that do not depend on the details of the PNG image data
01254     * being processed.
01255     */
01256 
01257 #ifdef PNG_READ_GAMMA_SUPPORTED
01258    /* Prior to 1.5.4 these tests were performed from png_set_gamma, 1.5.4 adds
01259     * png_set_alpha_mode and this is another source for a default file gamma so
01260     * the test needs to be performed later - here.  In addition prior to 1.5.4
01261     * the tests were repeated for the PALETTE color type here - this is no
01262     * longer necessary (and doesn't seem to have been necessary before.)
01263     */
01264    {
01265       /* The following temporary indicates if overall gamma correction is
01266        * required.
01267        */
01268       int gamma_correction = 0;
01269 
01270       if (png_ptr->gamma != 0) /* has been set */
01271       {
01272          if (png_ptr->screen_gamma != 0) /* screen set too */
01273             gamma_correction = png_gamma_threshold(png_ptr->gamma,
01274                png_ptr->screen_gamma);
01275 
01276          else
01277             /* Assume the output matches the input; a long time default behavior
01278              * of libpng, although the standard has nothing to say about this.
01279              */
01280             png_ptr->screen_gamma = png_reciprocal(png_ptr->gamma);
01281       }
01282 
01283       else if (png_ptr->screen_gamma != 0)
01284          /* The converse - assume the file matches the screen, note that this
01285           * perhaps undesireable default can (from 1.5.4) be changed by calling
01286           * png_set_alpha_mode (even if the alpha handling mode isn't required
01287           * or isn't changed from the default.)
01288           */
01289          png_ptr->gamma = png_reciprocal(png_ptr->screen_gamma);
01290 
01291       else /* neither are set */
01292          /* Just in case the following prevents any processing - file and screen
01293           * are both assumed to be linear and there is no way to introduce a
01294           * third gamma value other than png_set_background with 'UNIQUE', and,
01295           * prior to 1.5.4
01296           */
01297          png_ptr->screen_gamma = png_ptr->gamma = PNG_FP_1;
01298 
01299       /* Now turn the gamma transformation on or off as appropriate.  Notice
01300        * that PNG_GAMMA just refers to the file->screen correction.  Alpha
01301        * composition may independently cause gamma correction because it needs
01302        * linear data (e.g. if the file has a gAMA chunk but the screen gamma
01303        * hasn't been specified.)  In any case this flag may get turned off in
01304        * the code immediately below if the transform can be handled outside the
01305        * row loop.
01306        */
01307       if (gamma_correction)
01308          png_ptr->transformations |= PNG_GAMMA;
01309 
01310       else
01311          png_ptr->transformations &= ~PNG_GAMMA;
01312    }
01313 #endif
01314 
01315    /* Certain transformations have the effect of preventing other
01316     * transformations that happen afterward in png_do_read_transformations,
01317     * resolve the interdependencies here.  From the code of
01318     * png_do_read_transformations the order is:
01319     *
01320     *  1) PNG_EXPAND (including PNG_EXPAND_tRNS)
01321     *  2) PNG_STRIP_ALPHA (if no compose)
01322     *  3) PNG_RGB_TO_GRAY
01323     *  4) PNG_GRAY_TO_RGB iff !PNG_BACKGROUND_IS_GRAY
01324     *  5) PNG_COMPOSE
01325     *  6) PNG_GAMMA
01326     *  7) PNG_STRIP_ALPHA (if compose)
01327     *  8) PNG_ENCODE_ALPHA
01328     *  9) PNG_SCALE_16_TO_8
01329     * 10) PNG_16_TO_8
01330     * 11) PNG_QUANTIZE (converts to palette)
01331     * 12) PNG_EXPAND_16
01332     * 13) PNG_GRAY_TO_RGB iff PNG_BACKGROUND_IS_GRAY
01333     * 14) PNG_INVERT_MONO
01334     * 15) PNG_SHIFT
01335     * 16) PNG_PACK
01336     * 17) PNG_BGR
01337     * 18) PNG_PACKSWAP
01338     * 19) PNG_FILLER (includes PNG_ADD_ALPHA)
01339     * 20) PNG_INVERT_ALPHA
01340     * 21) PNG_SWAP_ALPHA
01341     * 22) PNG_SWAP_BYTES
01342     * 23) PNG_USER_TRANSFORM [must be last]
01343     */
01344 #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
01345    if ((png_ptr->transformations & PNG_STRIP_ALPHA) &&
01346       !(png_ptr->transformations & PNG_COMPOSE))
01347    {
01348       /* Stripping the alpha channel happens immediately after the 'expand'
01349        * transformations, before all other transformation, so it cancels out
01350        * the alpha handling.  It has the side effect negating the effect of
01351        * PNG_EXPAND_tRNS too:
01352        */
01353       png_ptr->transformations &= ~(PNG_BACKGROUND_EXPAND | PNG_ENCODE_ALPHA |
01354          PNG_EXPAND_tRNS);
01355       png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
01356 
01357       /* Kill the tRNS chunk itself too.  Prior to 1.5.4 this did not happen
01358        * so transparency information would remain just so long as it wasn't
01359        * expanded.  This produces unexpected API changes if the set of things
01360        * that do PNG_EXPAND_tRNS changes (perfectly possible given the
01361        * documentation - which says ask for what you want, accept what you
01362        * get.)  This makes the behavior consistent from 1.5.4:
01363        */
01364       png_ptr->num_trans = 0;
01365    }
01366 #endif /* STRIP_ALPHA supported, no COMPOSE */
01367 
01368 #ifdef PNG_READ_ALPHA_MODE_SUPPORTED
01369    /* If the screen gamma is about 1.0 then the OPTIMIZE_ALPHA and ENCODE_ALPHA
01370     * settings will have no effect.
01371     */
01372    if (!png_gamma_significant(png_ptr->screen_gamma))
01373    {
01374       png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
01375       png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
01376    }
01377 #endif
01378 
01379 #if defined(PNG_READ_EXPAND_SUPPORTED) && \
01380    defined(PNG_READ_BACKGROUND_SUPPORTED) && \
01381    defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
01382    /* Detect gray background and attempt to enable optimization for
01383     * gray --> RGB case.
01384     *
01385     * Note:  if PNG_BACKGROUND_EXPAND is set and color_type is either RGB or
01386     * RGB_ALPHA (in which case need_expand is superfluous anyway), the
01387     * background color might actually be gray yet not be flagged as such.
01388     * This is not a problem for the current code, which uses
01389     * PNG_BACKGROUND_IS_GRAY only to decide when to do the
01390     * png_do_gray_to_rgb() transformation.
01391     *
01392     * TODO: this code needs to be revised to avoid the complexity and
01393     * interdependencies.  The color type of the background should be recorded in
01394     * png_set_background, along with the bit depth, then the code has a record
01395     * of exactly what color space the background is currently in.
01396     */
01397    if (png_ptr->transformations & PNG_BACKGROUND_EXPAND)
01398    {
01399       /* PNG_BACKGROUND_EXPAND: the background is in the file color space, so if
01400        * the file was grayscale the background value is gray.
01401        */
01402       if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR))
01403          png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
01404    }
01405 
01406    else if (png_ptr->transformations & PNG_COMPOSE)
01407    {
01408       /* PNG_COMPOSE: png_set_background was called with need_expand false,
01409        * so the color is in the color space of the output or png_set_alpha_mode
01410        * was called and the color is black.  Ignore RGB_TO_GRAY because that
01411        * happens before GRAY_TO_RGB.
01412        */
01413       if (png_ptr->transformations & PNG_GRAY_TO_RGB)
01414       {
01415          if (png_ptr->background.red == png_ptr->background.green &&
01416              png_ptr->background.red == png_ptr->background.blue)
01417          {
01418             png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
01419             png_ptr->background.gray = png_ptr->background.red;
01420          }
01421       }
01422    }
01423 #endif /* PNG_READ_GRAY_TO_RGB_SUPPORTED (etc) */
01424 
01425    /* For indexed PNG data (PNG_COLOR_TYPE_PALETTE) many of the transformations
01426     * can be performed directly on the palette, and some (such as rgb to gray)
01427     * can be optimized inside the palette.  This is particularly true of the
01428     * composite (background and alpha) stuff, which can be pretty much all done
01429     * in the palette even if the result is expanded to RGB or gray afterward.
01430     *
01431     * NOTE: this is Not Yet Implemented, the code behaves as in 1.5.1 and
01432     * earlier and the palette stuff is actually handled on the first row.  This
01433     * leads to the reported bug that the palette returned by png_get_PLTE is not
01434     * updated.
01435     */
01436    if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
01437       png_init_palette_transformations(png_ptr);
01438 
01439    else
01440       png_init_rgb_transformations(png_ptr);
01441 
01442 #if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
01443    defined(PNG_READ_EXPAND_16_SUPPORTED)
01444    if ((png_ptr->transformations & PNG_EXPAND_16) &&
01445       (png_ptr->transformations & PNG_COMPOSE) &&
01446       !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
01447       png_ptr->bit_depth != 16)
01448    {
01449       /* TODO: fix this.  Because the expand_16 operation is after the compose
01450        * handling the background color must be 8, not 16, bits deep, but the
01451        * application will supply a 16-bit value so reduce it here.
01452        *
01453        * The PNG_BACKGROUND_EXPAND code above does not expand to 16 bits at
01454        * present, so that case is ok (until do_expand_16 is moved.)
01455        *
01456        * NOTE: this discards the low 16 bits of the user supplied background
01457        * color, but until expand_16 works properly there is no choice!
01458        */
01459 #     define CHOP(x) (x)=((png_uint_16)(((png_uint_32)(x)*255+32895) >> 16))
01460       CHOP(png_ptr->background.red);
01461       CHOP(png_ptr->background.green);
01462       CHOP(png_ptr->background.blue);
01463       CHOP(png_ptr->background.gray);
01464 #     undef CHOP
01465    }
01466 #endif /* PNG_READ_BACKGROUND_SUPPORTED && PNG_READ_EXPAND_16_SUPPORTED */
01467 
01468 #if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
01469    (defined(PNG_READ_SCALE_16_TO_8_SUPPORTED) || \
01470    defined(PNG_READ_STRIP_16_TO_8_SUPPORTED))
01471    if ((png_ptr->transformations & (PNG_16_TO_8|PNG_SCALE_16_TO_8)) &&
01472       (png_ptr->transformations & PNG_COMPOSE) &&
01473       !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
01474       png_ptr->bit_depth == 16)
01475    {
01476       /* On the other hand, if a 16-bit file is to be reduced to 8-bits per
01477        * component this will also happen after PNG_COMPOSE and so the background
01478        * color must be pre-expanded here.
01479        *
01480        * TODO: fix this too.
01481        */
01482       png_ptr->background.red = (png_uint_16)(png_ptr->background.red * 257);
01483       png_ptr->background.green =
01484          (png_uint_16)(png_ptr->background.green * 257);
01485       png_ptr->background.blue = (png_uint_16)(png_ptr->background.blue * 257);
01486       png_ptr->background.gray = (png_uint_16)(png_ptr->background.gray * 257);
01487    }
01488 #endif
01489 
01490    /* NOTE: below 'PNG_READ_ALPHA_MODE_SUPPORTED' is presumed to also enable the
01491     * background support (see the comments in scripts/pnglibconf.dfa), this
01492     * allows pre-multiplication of the alpha channel to be implemented as
01493     * compositing on black.  This is probably sub-optimal and has been done in
01494     * 1.5.4 betas simply to enable external critique and testing (i.e. to
01495     * implement the new API quickly, without lots of internal changes.)
01496     */
01497 
01498 #ifdef PNG_READ_GAMMA_SUPPORTED
01499 #  ifdef PNG_READ_BACKGROUND_SUPPORTED
01500       /* Includes ALPHA_MODE */
01501       png_ptr->background_1 = png_ptr->background;
01502 #  endif
01503 
01504    /* This needs to change - in the palette image case a whole set of tables are
01505     * built when it would be quicker to just calculate the correct value for
01506     * each palette entry directly.  Also, the test is too tricky - why check
01507     * PNG_RGB_TO_GRAY if PNG_GAMMA is not set?  The answer seems to be that
01508     * PNG_GAMMA is cancelled even if the gamma is known?  The test excludes the
01509     * PNG_COMPOSE case, so apparently if there is no *overall* gamma correction
01510     * the gamma tables will not be built even if composition is required on a
01511     * gamma encoded value.
01512     *
01513     * In 1.5.4 this is addressed below by an additional check on the individual
01514     * file gamma - if it is not 1.0 both RGB_TO_GRAY and COMPOSE need the
01515     * tables.
01516     */
01517    if ((png_ptr->transformations & PNG_GAMMA)
01518       || ((png_ptr->transformations & PNG_RGB_TO_GRAY)
01519          && (png_gamma_significant(png_ptr->gamma) ||
01520             png_gamma_significant(png_ptr->screen_gamma)))
01521       || ((png_ptr->transformations & PNG_COMPOSE)
01522          && (png_gamma_significant(png_ptr->gamma)
01523             || png_gamma_significant(png_ptr->screen_gamma)
01524 #  ifdef PNG_READ_BACKGROUND_SUPPORTED
01525             || (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_UNIQUE
01526                && png_gamma_significant(png_ptr->background_gamma))
01527 #  endif
01528       )) || ((png_ptr->transformations & PNG_ENCODE_ALPHA)
01529          && png_gamma_significant(png_ptr->screen_gamma))
01530       )
01531    {
01532       png_build_gamma_table(png_ptr, png_ptr->bit_depth);
01533 
01534 #ifdef PNG_READ_BACKGROUND_SUPPORTED
01535       if (png_ptr->transformations & PNG_COMPOSE)
01536       {
01537          /* Issue a warning about this combination: because RGB_TO_GRAY is
01538           * optimized to do the gamma transform if present yet do_background has
01539           * to do the same thing if both options are set a
01540           * double-gamma-correction happens.  This is true in all versions of
01541           * libpng to date.
01542           */
01543          if (png_ptr->transformations & PNG_RGB_TO_GRAY)
01544             png_warning(png_ptr,
01545                "libpng does not support gamma+background+rgb_to_gray");
01546 
01547          if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
01548          {
01549             /* We don't get to here unless there is a tRNS chunk with non-opaque
01550              * entries - see the checking code at the start of this function.
01551              */
01552             png_color back, back_1;
01553             png_colorp palette = png_ptr->palette;
01554             int num_palette = png_ptr->num_palette;
01555             int i;
01556             if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
01557             {
01558 
01559                back.red = png_ptr->gamma_table[png_ptr->background.red];
01560                back.green = png_ptr->gamma_table[png_ptr->background.green];
01561                back.blue = png_ptr->gamma_table[png_ptr->background.blue];
01562 
01563                back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
01564                back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
01565                back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
01566             }
01567             else
01568             {
01569                png_fixed_point g, gs;
01570 
01571                switch (png_ptr->background_gamma_type)
01572                {
01573                   case PNG_BACKGROUND_GAMMA_SCREEN:
01574                      g = (png_ptr->screen_gamma);
01575                      gs = PNG_FP_1;
01576                      break;
01577 
01578                   case PNG_BACKGROUND_GAMMA_FILE:
01579                      g = png_reciprocal(png_ptr->gamma);
01580                      gs = png_reciprocal2(png_ptr->gamma,
01581                         png_ptr->screen_gamma);
01582                      break;
01583 
01584                   case PNG_BACKGROUND_GAMMA_UNIQUE:
01585                      g = png_reciprocal(png_ptr->background_gamma);
01586                      gs = png_reciprocal2(png_ptr->background_gamma,
01587                         png_ptr->screen_gamma);
01588                      break;
01589                   default:
01590                      g = PNG_FP_1;    /* back_1 */
01591                      gs = PNG_FP_1;   /* back */
01592                      break;
01593                }
01594 
01595                if (png_gamma_significant(gs))
01596                {
01597                   back.red = png_gamma_8bit_correct(png_ptr->background.red,
01598                       gs);
01599                   back.green = png_gamma_8bit_correct(png_ptr->background.green,
01600                       gs);
01601                   back.blue = png_gamma_8bit_correct(png_ptr->background.blue,
01602                       gs);
01603                }
01604 
01605                else
01606                {
01607                   back.red   = (png_byte)png_ptr->background.red;
01608                   back.green = (png_byte)png_ptr->background.green;
01609                   back.blue  = (png_byte)png_ptr->background.blue;
01610                }
01611 
01612                if (png_gamma_significant(g))
01613                {
01614                   back_1.red = png_gamma_8bit_correct(png_ptr->background.red,
01615                      g);
01616                   back_1.green = png_gamma_8bit_correct(
01617                      png_ptr->background.green, g);
01618                   back_1.blue = png_gamma_8bit_correct(png_ptr->background.blue,
01619                      g);
01620                }
01621 
01622                else
01623                {
01624                   back_1.red   = (png_byte)png_ptr->background.red;
01625                   back_1.green = (png_byte)png_ptr->background.green;
01626                   back_1.blue  = (png_byte)png_ptr->background.blue;
01627                }
01628             }
01629 
01630             for (i = 0; i < num_palette; i++)
01631             {
01632                if (i < (int)png_ptr->num_trans &&
01633                    png_ptr->trans_alpha[i] != 0xff)
01634                {
01635                   if (png_ptr->trans_alpha[i] == 0)
01636                   {
01637                      palette[i] = back;
01638                   }
01639                   else /* if (png_ptr->trans_alpha[i] != 0xff) */
01640                   {
01641                      png_byte v, w;
01642 
01643                      v = png_ptr->gamma_to_1[palette[i].red];
01644                      png_composite(w, v, png_ptr->trans_alpha[i], back_1.red);
01645                      palette[i].red = png_ptr->gamma_from_1[w];
01646 
01647                      v = png_ptr->gamma_to_1[palette[i].green];
01648                      png_composite(w, v, png_ptr->trans_alpha[i], back_1.green);
01649                      palette[i].green = png_ptr->gamma_from_1[w];
01650 
01651                      v = png_ptr->gamma_to_1[palette[i].blue];
01652                      png_composite(w, v, png_ptr->trans_alpha[i], back_1.blue);
01653                      palette[i].blue = png_ptr->gamma_from_1[w];
01654                   }
01655                }
01656                else
01657                {
01658                   palette[i].red = png_ptr->gamma_table[palette[i].red];
01659                   palette[i].green = png_ptr->gamma_table[palette[i].green];
01660                   palette[i].blue = png_ptr->gamma_table[palette[i].blue];
01661                }
01662             }
01663 
01664             /* Prevent the transformations being done again.
01665              *
01666              * NOTE: this is highly dubious; it removes the transformations in
01667              * place.  This seems inconsistent with the general treatment of the
01668              * transformations elsewhere.
01669              */
01670             png_ptr->transformations &= ~(PNG_COMPOSE | PNG_GAMMA);
01671          } /* color_type == PNG_COLOR_TYPE_PALETTE */
01672 
01673          /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */
01674          else /* color_type != PNG_COLOR_TYPE_PALETTE */
01675          {
01676             int gs_sig, g_sig;
01677             png_fixed_point g = PNG_FP_1;  /* Correction to linear */
01678             png_fixed_point gs = PNG_FP_1; /* Correction to screen */
01679 
01680             switch (png_ptr->background_gamma_type)
01681             {
01682                case PNG_BACKGROUND_GAMMA_SCREEN:
01683                   g = png_ptr->screen_gamma;
01684                   /* gs = PNG_FP_1; */
01685                   break;
01686 
01687                case PNG_BACKGROUND_GAMMA_FILE:
01688                   g = png_reciprocal(png_ptr->gamma);
01689                   gs = png_reciprocal2(png_ptr->gamma, png_ptr->screen_gamma);
01690                   break;
01691 
01692                case PNG_BACKGROUND_GAMMA_UNIQUE:
01693                   g = png_reciprocal(png_ptr->background_gamma);
01694                   gs = png_reciprocal2(png_ptr->background_gamma,
01695                       png_ptr->screen_gamma);
01696                   break;
01697 
01698                default:
01699                   png_error(png_ptr, "invalid background gamma type");
01700             }
01701 
01702             g_sig = png_gamma_significant(g);
01703             gs_sig = png_gamma_significant(gs);
01704 
01705             if (g_sig)
01706                png_ptr->background_1.gray = png_gamma_correct(png_ptr,
01707                    png_ptr->background.gray, g);
01708 
01709             if (gs_sig)
01710                png_ptr->background.gray = png_gamma_correct(png_ptr,
01711                    png_ptr->background.gray, gs);
01712 
01713             if ((png_ptr->background.red != png_ptr->background.green) ||
01714                 (png_ptr->background.red != png_ptr->background.blue) ||
01715                 (png_ptr->background.red != png_ptr->background.gray))
01716             {
01717                /* RGB or RGBA with color background */
01718                if (g_sig)
01719                {
01720                   png_ptr->background_1.red = png_gamma_correct(png_ptr,
01721                       png_ptr->background.red, g);
01722 
01723                   png_ptr->background_1.green = png_gamma_correct(png_ptr,
01724                       png_ptr->background.green, g);
01725 
01726                   png_ptr->background_1.blue = png_gamma_correct(png_ptr,
01727                       png_ptr->background.blue, g);
01728                }
01729 
01730                if (gs_sig)
01731                {
01732                   png_ptr->background.red = png_gamma_correct(png_ptr,
01733                       png_ptr->background.red, gs);
01734 
01735                   png_ptr->background.green = png_gamma_correct(png_ptr,
01736                       png_ptr->background.green, gs);
01737 
01738                   png_ptr->background.blue = png_gamma_correct(png_ptr,
01739                       png_ptr->background.blue, gs);
01740                }
01741             }
01742 
01743             else
01744             {
01745                /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */
01746                png_ptr->background_1.red = png_ptr->background_1.green
01747                    = png_ptr->background_1.blue = png_ptr->background_1.gray;
01748 
01749                png_ptr->background.red = png_ptr->background.green
01750                    = png_ptr->background.blue = png_ptr->background.gray;
01751             }
01752 
01753             /* The background is now in screen gamma: */
01754             png_ptr->background_gamma_type = PNG_BACKGROUND_GAMMA_SCREEN;
01755          } /* color_type != PNG_COLOR_TYPE_PALETTE */
01756       }/* png_ptr->transformations & PNG_BACKGROUND */
01757 
01758       else
01759       /* Transformation does not include PNG_BACKGROUND */
01760 #endif /* PNG_READ_BACKGROUND_SUPPORTED */
01761       if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE
01762 #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
01763          /* RGB_TO_GRAY needs to have non-gamma-corrected values! */
01764          && ((png_ptr->transformations & PNG_EXPAND) == 0 ||
01765          (png_ptr->transformations & PNG_RGB_TO_GRAY) == 0)
01766 #endif
01767          )
01768       {
01769          png_colorp palette = png_ptr->palette;
01770          int num_palette = png_ptr->num_palette;
01771          int i;
01772 
01773          /*NOTE: there are other transformations that should probably be in here
01774           * too.
01775           */
01776          for (i = 0; i < num_palette; i++)
01777          {
01778             palette[i].red = png_ptr->gamma_table[palette[i].red];
01779             palette[i].green = png_ptr->gamma_table[palette[i].green];
01780             palette[i].blue = png_ptr->gamma_table[palette[i].blue];
01781          }
01782 
01783          /* Done the gamma correction. */
01784          png_ptr->transformations &= ~PNG_GAMMA;
01785       } /* color_type == PALETTE && !PNG_BACKGROUND transformation */
01786    }
01787 #ifdef PNG_READ_BACKGROUND_SUPPORTED
01788    else
01789 #endif
01790 #endif /* PNG_READ_GAMMA_SUPPORTED */
01791 
01792 #ifdef PNG_READ_BACKGROUND_SUPPORTED
01793    /* No GAMMA transformation (see the hanging else 4 lines above) */
01794    if ((png_ptr->transformations & PNG_COMPOSE) &&
01795        (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))
01796    {
01797       int i;
01798       int istop = (int)png_ptr->num_trans;
01799       png_color back;
01800       png_colorp palette = png_ptr->palette;
01801 
01802       back.red   = (png_byte)png_ptr->background.red;
01803       back.green = (png_byte)png_ptr->background.green;
01804       back.blue  = (png_byte)png_ptr->background.blue;
01805 
01806       for (i = 0; i < istop; i++)
01807       {
01808          if (png_ptr->trans_alpha[i] == 0)
01809          {
01810             palette[i] = back;
01811          }
01812 
01813          else if (png_ptr->trans_alpha[i] != 0xff)
01814          {
01815             /* The png_composite() macro is defined in png.h */
01816             png_composite(palette[i].red, palette[i].red,
01817                 png_ptr->trans_alpha[i], back.red);
01818 
01819             png_composite(palette[i].green, palette[i].green,
01820                 png_ptr->trans_alpha[i], back.green);
01821 
01822             png_composite(palette[i].blue, palette[i].blue,
01823                 png_ptr->trans_alpha[i], back.blue);
01824          }
01825       }
01826 
01827       png_ptr->transformations &= ~PNG_COMPOSE;
01828    }
01829 #endif /* PNG_READ_BACKGROUND_SUPPORTED */
01830 
01831 #ifdef PNG_READ_SHIFT_SUPPORTED
01832    if ((png_ptr->transformations & PNG_SHIFT) &&
01833        (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))
01834    {
01835       int i;
01836       int istop = png_ptr->num_palette;
01837       int shift = 8 - png_ptr->sig_bit.red;
01838 
01839       /* significant bits can be in the range 1 to 7 for a meaninful result, if
01840        * the number of significant bits is 0 then no shift is done (this is an
01841        * error condition which is silently ignored.)
01842        */
01843       if (shift > 0 && shift < 8) for (i=0; i<istop; ++i)
01844       {
01845          int component = png_ptr->palette[i].red;
01846 
01847          component >>= shift;
01848          png_ptr->palette[i].red = (png_byte)component;
01849       }
01850 
01851       shift = 8 - png_ptr->sig_bit.green;
01852       if (shift > 0 && shift < 8) for (i=0; i<istop; ++i)
01853       {
01854          int component = png_ptr->palette[i].green;
01855 
01856          component >>= shift;
01857          png_ptr->palette[i].green = (png_byte)component;
01858       }
01859 
01860       shift = 8 - png_ptr->sig_bit.blue;
01861       if (shift > 0 && shift < 8) for (i=0; i<istop; ++i)
01862       {
01863          int component = png_ptr->palette[i].blue;
01864 
01865          component >>= shift;
01866          png_ptr->palette[i].blue = (png_byte)component;
01867       }
01868    }
01869 #endif  /* PNG_READ_SHIFT_SUPPORTED */
01870 }
01871 
01872 /* Modify the info structure to reflect the transformations.  The
01873  * info should be updated so a PNG file could be written with it,
01874  * assuming the transformations result in valid PNG data.
01875  */
01876 void /* PRIVATE */
01877 png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
01878 {
01879    png_debug(1, "in png_read_transform_info");
01880 
01881 #ifdef PNG_READ_EXPAND_SUPPORTED
01882    if (png_ptr->transformations & PNG_EXPAND)
01883    {
01884       if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
01885       {
01886          /* This check must match what actually happens in
01887           * png_do_expand_palette; if it ever checks the tRNS chunk to see if
01888           * it is all opaque we must do the same (at present it does not.)
01889           */
01890          if (png_ptr->num_trans > 0)
01891             info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
01892 
01893          else
01894             info_ptr->color_type = PNG_COLOR_TYPE_RGB;
01895 
01896          info_ptr->bit_depth = 8;
01897          info_ptr->num_trans = 0;
01898       }
01899       else
01900       {
01901          if (png_ptr->num_trans)
01902          {
01903             if (png_ptr->transformations & PNG_EXPAND_tRNS)
01904                info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
01905          }
01906          if (info_ptr->bit_depth < 8)
01907             info_ptr->bit_depth = 8;
01908 
01909          info_ptr->num_trans = 0;
01910       }
01911    }
01912 #endif
01913 
01914 #if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
01915    defined(PNG_READ_ALPHA_MODE_SUPPORTED)
01916    /* The following is almost certainly wrong unless the background value is in
01917     * the screen space!
01918     */
01919    if (png_ptr->transformations & PNG_COMPOSE)
01920       info_ptr->background = png_ptr->background;
01921 #endif
01922 
01923 #ifdef PNG_READ_GAMMA_SUPPORTED
01924    /* The following used to be conditional on PNG_GAMMA (prior to 1.5.4),
01925     * however it seems that the code in png_init_read_transformations, which has
01926     * been called before this from png_read_update_info->png_read_start_row
01927     * sometimes does the gamma transform and cancels the flag.
01928     */
01929    info_ptr->gamma = png_ptr->gamma;
01930 #endif
01931 
01932    if (info_ptr->bit_depth == 16)
01933    {
01934 #  ifdef PNG_READ_16BIT_SUPPORTED
01935 #     ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
01936          if (png_ptr->transformations & PNG_SCALE_16_TO_8)
01937             info_ptr->bit_depth = 8;
01938 #     endif
01939 
01940 #     ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
01941          if (png_ptr->transformations & PNG_16_TO_8)
01942             info_ptr->bit_depth = 8;
01943 #     endif
01944 
01945 #  else
01946       /* No 16 bit support: force chopping 16-bit input down to 8, in this case
01947        * the app program can chose if both APIs are available by setting the
01948        * correct scaling to use.
01949        */
01950 #     ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
01951          /* For compatibility with previous versions use the strip method by
01952           * default.  This code works because if PNG_SCALE_16_TO_8 is already
01953           * set the code below will do that in preference to the chop.
01954           */
01955          png_ptr->transformations |= PNG_16_TO_8;
01956          info_ptr->bit_depth = 8;
01957 #     else
01958 
01959 #        ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
01960             png_ptr->transformations |= PNG_SCALE_16_TO_8;
01961             info_ptr->bit_depth = 8;
01962 #        else
01963 
01964             CONFIGURATION ERROR: you must enable at least one 16 to 8 method
01965 #        endif
01966 #    endif
01967 #endif /* !READ_16BIT_SUPPORTED */
01968    }
01969 
01970 #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
01971    if (png_ptr->transformations & PNG_GRAY_TO_RGB)
01972       info_ptr->color_type = (png_byte)(info_ptr->color_type |
01973          PNG_COLOR_MASK_COLOR);
01974 #endif
01975 
01976 #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
01977    if (png_ptr->transformations & PNG_RGB_TO_GRAY)
01978       info_ptr->color_type = (png_byte)(info_ptr->color_type &
01979          ~PNG_COLOR_MASK_COLOR);
01980 #endif
01981 
01982 #ifdef PNG_READ_QUANTIZE_SUPPORTED
01983    if (png_ptr->transformations & PNG_QUANTIZE)
01984    {
01985       if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
01986           (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) &&
01987           png_ptr->palette_lookup && info_ptr->bit_depth == 8)
01988       {
01989          info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
01990       }
01991    }
01992 #endif
01993 
01994 #ifdef PNG_READ_EXPAND_16_SUPPORTED
01995    if (png_ptr->transformations & PNG_EXPAND_16 && info_ptr->bit_depth == 8 &&
01996       info_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
01997    {
01998       info_ptr->bit_depth = 16;
01999    }
02000 #endif
02001 
02002 #ifdef PNG_READ_PACK_SUPPORTED
02003    if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8))
02004       info_ptr->bit_depth = 8;
02005 #endif
02006 
02007    if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
02008       info_ptr->channels = 1;
02009 
02010    else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
02011       info_ptr->channels = 3;
02012 
02013    else
02014       info_ptr->channels = 1;
02015 
02016 #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
02017    if (png_ptr->transformations & PNG_STRIP_ALPHA)
02018    {
02019       info_ptr->color_type = (png_byte)(info_ptr->color_type &
02020          ~PNG_COLOR_MASK_ALPHA);
02021       info_ptr->num_trans = 0;
02022    }
02023 #endif
02024 
02025    if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
02026       info_ptr->channels++;
02027 
02028 #ifdef PNG_READ_FILLER_SUPPORTED
02029    /* STRIP_ALPHA and FILLER allowed:  MASK_ALPHA bit stripped above */
02030    if ((png_ptr->transformations & PNG_FILLER) &&
02031        ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
02032        (info_ptr->color_type == PNG_COLOR_TYPE_GRAY)))
02033    {
02034       info_ptr->channels++;
02035       /* If adding a true alpha channel not just filler */
02036       if (png_ptr->transformations & PNG_ADD_ALPHA)
02037          info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
02038    }
02039 #endif
02040 
02041 #if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \
02042 defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
02043    if (png_ptr->transformations & PNG_USER_TRANSFORM)
02044    {
02045       if (info_ptr->bit_depth < png_ptr->user_transform_depth)
02046          info_ptr->bit_depth = png_ptr->user_transform_depth;
02047 
02048       if (info_ptr->channels < png_ptr->user_transform_channels)
02049          info_ptr->channels = png_ptr->user_transform_channels;
02050    }
02051 #endif
02052 
02053    info_ptr->pixel_depth = (png_byte)(info_ptr->channels *
02054        info_ptr->bit_depth);
02055 
02056    info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, info_ptr->width);
02057 
02058    /* Adding in 1.5.4: cache the above value in png_struct so that we can later
02059     * check in png_rowbytes that the user buffer won't get overwritten.  Note
02060     * that the field is not always set - if png_read_update_info isn't called
02061     * the application has to either not do any transforms or get the calculation
02062     * right itself.
02063     */
02064    png_ptr->info_rowbytes = info_ptr->rowbytes;
02065 
02066 #ifndef PNG_READ_EXPAND_SUPPORTED
02067    if (png_ptr)
02068       return;
02069 #endif
02070 }
02071 
02072 /* Transform the row.  The order of transformations is significant,
02073  * and is very touchy.  If you add a transformation, take care to
02074  * decide how it fits in with the other transformations here.
02075  */
02076 void /* PRIVATE */
02077 png_do_read_transformations(png_structp png_ptr, png_row_infop row_info)
02078 {
02079    png_debug(1, "in png_do_read_transformations");
02080 
02081    if (png_ptr->row_buf == NULL)
02082    {
02083       /* Prior to 1.5.4 this output row/pass where the NULL pointer is, but this
02084        * error is incredibly rare and incredibly easy to debug without this
02085        * information.
02086        */
02087       png_error(png_ptr, "NULL row buffer");
02088    }
02089 
02090    /* The following is debugging; prior to 1.5.4 the code was never compiled in;
02091     * in 1.5.4 PNG_FLAG_DETECT_UNINITIALIZED was added and the macro
02092     * PNG_WARN_UNINITIALIZED_ROW removed.  In 1.5 the new flag is set only for
02093     * selected new APIs to ensure that there is no API change.
02094     */
02095    if ((png_ptr->flags & PNG_FLAG_DETECT_UNINITIALIZED) != 0 &&
02096       !(png_ptr->flags & PNG_FLAG_ROW_INIT))
02097    {
02098       /* Application has failed to call either png_read_start_image() or
02099        * png_read_update_info() after setting transforms that expand pixels.
02100        * This check added to libpng-1.2.19 (but not enabled until 1.5.4).
02101        */
02102       png_error(png_ptr, "Uninitialized row");
02103    }
02104 
02105 #ifdef PNG_READ_EXPAND_SUPPORTED
02106    if (png_ptr->transformations & PNG_EXPAND)
02107    {
02108       if (row_info->color_type == PNG_COLOR_TYPE_PALETTE)
02109       {
02110          png_do_expand_palette(row_info, png_ptr->row_buf + 1,
02111              png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans);
02112       }
02113 
02114       else
02115       {
02116          if (png_ptr->num_trans &&
02117              (png_ptr->transformations & PNG_EXPAND_tRNS))
02118             png_do_expand(row_info, png_ptr->row_buf + 1,
02119                 &(png_ptr->trans_color));
02120 
02121          else
02122             png_do_expand(row_info, png_ptr->row_buf + 1,
02123                 NULL);
02124       }
02125    }
02126 #endif
02127 
02128 #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
02129    if ((png_ptr->transformations & PNG_STRIP_ALPHA) &&
02130       !(png_ptr->transformations & PNG_COMPOSE) &&
02131       (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
02132       row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
02133       png_do_strip_channel(row_info, png_ptr->row_buf + 1,
02134          0 /* at_start == false, because SWAP_ALPHA happens later */);
02135 #endif
02136 
02137 #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
02138    if (png_ptr->transformations & PNG_RGB_TO_GRAY)
02139    {
02140       int rgb_error =
02141           png_do_rgb_to_gray(png_ptr, row_info,
02142               png_ptr->row_buf + 1);
02143 
02144       if (rgb_error)
02145       {
02146          png_ptr->rgb_to_gray_status=1;
02147          if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
02148              PNG_RGB_TO_GRAY_WARN)
02149             png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel");
02150 
02151          if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
02152              PNG_RGB_TO_GRAY_ERR)
02153             png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel");
02154       }
02155    }
02156 #endif
02157 
02158 /* From Andreas Dilger e-mail to png-implement, 26 March 1998:
02159  *
02160  *   In most cases, the "simple transparency" should be done prior to doing
02161  *   gray-to-RGB, or you will have to test 3x as many bytes to check if a
02162  *   pixel is transparent.  You would also need to make sure that the
02163  *   transparency information is upgraded to RGB.
02164  *
02165  *   To summarize, the current flow is:
02166  *   - Gray + simple transparency -> compare 1 or 2 gray bytes and composite
02167  *                                   with background "in place" if transparent,
02168  *                                   convert to RGB if necessary
02169  *   - Gray + alpha -> composite with gray background and remove alpha bytes,
02170  *                                   convert to RGB if necessary
02171  *
02172  *   To support RGB backgrounds for gray images we need:
02173  *   - Gray + simple transparency -> convert to RGB + simple transparency,
02174  *                                   compare 3 or 6 bytes and composite with
02175  *                                   background "in place" if transparent
02176  *                                   (3x compare/pixel compared to doing
02177  *                                   composite with gray bkgrnd)
02178  *   - Gray + alpha -> convert to RGB + alpha, composite with background and
02179  *                                   remove alpha bytes (3x float
02180  *                                   operations/pixel compared with composite
02181  *                                   on gray background)
02182  *
02183  *  Greg's change will do this.  The reason it wasn't done before is for
02184  *  performance, as this increases the per-pixel operations.  If we would check
02185  *  in advance if the background was gray or RGB, and position the gray-to-RGB
02186  *  transform appropriately, then it would save a lot of work/time.
02187  */
02188 
02189 #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
02190    /* If gray -> RGB, do so now only if background is non-gray; else do later
02191     * for performance reasons
02192     */
02193    if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
02194        !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
02195       png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1);
02196 #endif
02197 
02198 #if (defined PNG_READ_BACKGROUND_SUPPORTED) ||\
02199    (defined PNG_READ_ALPHA_MODE_SUPPORTED)
02200    if (png_ptr->transformations & PNG_COMPOSE)
02201       png_do_compose(row_info, png_ptr->row_buf + 1, png_ptr);
02202 #endif
02203 
02204 #ifdef PNG_READ_GAMMA_SUPPORTED
02205    if ((png_ptr->transformations & PNG_GAMMA) &&
02206 #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
02207       /* Because RGB_TO_GRAY does the gamma transform. */
02208       !(png_ptr->transformations & PNG_RGB_TO_GRAY) &&
02209 #endif
02210 #if (defined PNG_READ_BACKGROUND_SUPPORTED) ||\
02211    (defined PNG_READ_ALPHA_MODE_SUPPORTED)
02212       /* Because PNG_COMPOSE does the gamma transform if there is something to
02213        * do (if there is an alpha channel or transparency.)
02214        */
02215        !((png_ptr->transformations & PNG_COMPOSE) &&
02216        ((png_ptr->num_trans != 0) ||
02217        (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) &&
02218 #endif
02219       /* Because png_init_read_transformations transforms the palette, unless
02220        * RGB_TO_GRAY will do the transform.
02221        */
02222        (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE))
02223       png_do_gamma(row_info, png_ptr->row_buf + 1, png_ptr);
02224 #endif
02225 
02226 #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
02227    if ((png_ptr->transformations & PNG_STRIP_ALPHA) &&
02228       (png_ptr->transformations & PNG_COMPOSE) &&
02229       (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
02230       row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
02231       png_do_strip_channel(row_info, png_ptr->row_buf + 1,
02232          0 /* at_start == false, because SWAP_ALPHA happens later */);
02233 #endif
02234 
02235 #ifdef PNG_READ_ALPHA_MODE_SUPPORTED
02236    if ((png_ptr->transformations & PNG_ENCODE_ALPHA) &&
02237       (row_info->color_type & PNG_COLOR_MASK_ALPHA))
02238       png_do_encode_alpha(row_info, png_ptr->row_buf + 1, png_ptr);
02239 #endif
02240 
02241 #ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
02242    if (png_ptr->transformations & PNG_SCALE_16_TO_8)
02243       png_do_scale_16_to_8(row_info, png_ptr->row_buf + 1);
02244 #endif
02245 
02246 #ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
02247    /* There is no harm in doing both of these because only one has any effect,
02248     * by putting the 'scale' option first if the app asks for scale (either by
02249     * calling the API or in a TRANSFORM flag) this is what happens.
02250     */
02251    if (png_ptr->transformations & PNG_16_TO_8)
02252       png_do_chop(row_info, png_ptr->row_buf + 1);
02253 #endif
02254 
02255 #ifdef PNG_READ_QUANTIZE_SUPPORTED
02256    if (png_ptr->transformations & PNG_QUANTIZE)
02257    {
02258       png_do_quantize(row_info, png_ptr->row_buf + 1,
02259           png_ptr->palette_lookup, png_ptr->quantize_index);
02260 
02261       if (row_info->rowbytes == 0)
02262          png_error(png_ptr, "png_do_quantize returned rowbytes=0");
02263    }
02264 #endif /* PNG_READ_QUANTIZE_SUPPORTED */
02265 
02266 #ifdef PNG_READ_EXPAND_16_SUPPORTED
02267    /* Do the expansion now, after all the arithmetic has been done.  Notice
02268     * that previous transformations can handle the PNG_EXPAND_16 flag if this
02269     * is efficient (particularly true in the case of gamma correction, where
02270     * better accuracy results faster!)
02271     */
02272    if (png_ptr->transformations & PNG_EXPAND_16)
02273       png_do_expand_16(row_info, png_ptr->row_buf + 1);
02274 #endif
02275 
02276 #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
02277    /*NOTE: moved here in 1.5.4 (from much later in this list.) */
02278    if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
02279        (png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
02280       png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1);
02281 #endif
02282 
02283 #ifdef PNG_READ_INVERT_SUPPORTED
02284    if (png_ptr->transformations & PNG_INVERT_MONO)
02285       png_do_invert(row_info, png_ptr->row_buf + 1);
02286 #endif
02287 
02288 #ifdef PNG_READ_SHIFT_SUPPORTED
02289    if (png_ptr->transformations & PNG_SHIFT)
02290       png_do_unshift(row_info, png_ptr->row_buf + 1,
02291           &(png_ptr->shift));
02292 #endif
02293 
02294 #ifdef PNG_READ_PACK_SUPPORTED
02295    if (png_ptr->transformations & PNG_PACK)
02296       png_do_unpack(row_info, png_ptr->row_buf + 1);
02297 #endif
02298 
02299 #ifdef PNG_READ_BGR_SUPPORTED
02300    if (png_ptr->transformations & PNG_BGR)
02301       png_do_bgr(row_info, png_ptr->row_buf + 1);
02302 #endif
02303 
02304 #ifdef PNG_READ_PACKSWAP_SUPPORTED
02305    if (png_ptr->transformations & PNG_PACKSWAP)
02306       png_do_packswap(row_info, png_ptr->row_buf + 1);
02307 #endif
02308 
02309 #ifdef PNG_READ_FILLER_SUPPORTED
02310    if (png_ptr->transformations & PNG_FILLER)
02311       png_do_read_filler(row_info, png_ptr->row_buf + 1,
02312           (png_uint_32)png_ptr->filler, png_ptr->flags);
02313 #endif
02314 
02315 #ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
02316    if (png_ptr->transformations & PNG_INVERT_ALPHA)
02317       png_do_read_invert_alpha(row_info, png_ptr->row_buf + 1);
02318 #endif
02319 
02320 #ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
02321    if (png_ptr->transformations & PNG_SWAP_ALPHA)
02322       png_do_read_swap_alpha(row_info, png_ptr->row_buf + 1);
02323 #endif
02324 
02325 #ifdef PNG_READ_16BIT_SUPPORTED
02326 #ifdef PNG_READ_SWAP_SUPPORTED
02327    if (png_ptr->transformations & PNG_SWAP_BYTES)
02328       png_do_swap(row_info, png_ptr->row_buf + 1);
02329 #endif
02330 #endif
02331 
02332 #ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
02333    if (png_ptr->transformations & PNG_USER_TRANSFORM)
02334     {
02335       if (png_ptr->read_user_transform_fn != NULL)
02336          (*(png_ptr->read_user_transform_fn)) /* User read transform function */
02337              (png_ptr,     /* png_ptr */
02338              row_info,     /* row_info: */
02339                 /*  png_uint_32 width;       width of row */
02340                 /*  png_size_t rowbytes;     number of bytes in row */
02341                 /*  png_byte color_type;     color type of pixels */
02342                 /*  png_byte bit_depth;      bit depth of samples */
02343                 /*  png_byte channels;       number of channels (1-4) */
02344                 /*  png_byte pixel_depth;    bits per pixel (depth*channels) */
02345              png_ptr->row_buf + 1);    /* start of pixel data for row */
02346 #ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
02347       if (png_ptr->user_transform_depth)
02348          row_info->bit_depth = png_ptr->user_transform_depth;
02349 
02350       if (png_ptr->user_transform_channels)
02351          row_info->channels = png_ptr->user_transform_channels;
02352 #endif
02353       row_info->pixel_depth = (png_byte)(row_info->bit_depth *
02354           row_info->channels);
02355 
02356       row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_info->width);
02357    }
02358 #endif
02359 }
02360 
02361 #ifdef PNG_READ_PACK_SUPPORTED
02362 /* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel,
02363  * without changing the actual values.  Thus, if you had a row with
02364  * a bit depth of 1, you would end up with bytes that only contained
02365  * the numbers 0 or 1.  If you would rather they contain 0 and 255, use
02366  * png_do_shift() after this.
02367  */
02368 void /* PRIVATE */
02369 png_do_unpack(png_row_infop row_info, png_bytep row)
02370 {
02371    png_debug(1, "in png_do_unpack");
02372 
02373    if (row_info->bit_depth < 8)
02374    {
02375       png_uint_32 i;
02376       png_uint_32 row_width=row_info->width;
02377 
02378       switch (row_info->bit_depth)
02379       {
02380          case 1:
02381          {
02382             png_bytep sp = row + (png_size_t)((row_width - 1) >> 3);
02383             png_bytep dp = row + (png_size_t)row_width - 1;
02384             png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07);
02385             for (i = 0; i < row_width; i++)
02386             {
02387                *dp = (png_byte)((*sp >> shift) & 0x01);
02388 
02389                if (shift == 7)
02390                {
02391                   shift = 0;
02392                   sp--;
02393                }
02394 
02395                else
02396                   shift++;
02397 
02398                dp--;
02399             }
02400             break;
02401          }
02402 
02403          case 2:
02404          {
02405 
02406             png_bytep sp = row + (png_size_t)((row_width - 1) >> 2);
02407             png_bytep dp = row + (png_size_t)row_width - 1;
02408             png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
02409             for (i = 0; i < row_width; i++)
02410             {
02411                *dp = (png_byte)((*sp >> shift) & 0x03);
02412 
02413                if (shift == 6)
02414                {
02415                   shift = 0;
02416                   sp--;
02417                }
02418 
02419                else
02420                   shift += 2;
02421 
02422                dp--;
02423             }
02424             break;
02425          }
02426 
02427          case 4:
02428          {
02429             png_bytep sp = row + (png_size_t)((row_width - 1) >> 1);
02430             png_bytep dp = row + (png_size_t)row_width - 1;
02431             png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
02432             for (i = 0; i < row_width; i++)
02433             {
02434                *dp = (png_byte)((*sp >> shift) & 0x0f);
02435 
02436                if (shift == 4)
02437                {
02438                   shift = 0;
02439                   sp--;
02440                }
02441 
02442                else
02443                   shift = 4;
02444 
02445                dp--;
02446             }
02447             break;
02448          }
02449 
02450          default:
02451             break;
02452       }
02453       row_info->bit_depth = 8;
02454       row_info->pixel_depth = (png_byte)(8 * row_info->channels);
02455       row_info->rowbytes = row_width * row_info->channels;
02456    }
02457 }
02458 #endif
02459 
02460 #ifdef PNG_READ_SHIFT_SUPPORTED
02461 /* Reverse the effects of png_do_shift.  This routine merely shifts the
02462  * pixels back to their significant bits values.  Thus, if you have
02463  * a row of bit depth 8, but only 5 are significant, this will shift
02464  * the values back to 0 through 31.
02465  */
02466 void /* PRIVATE */
02467 png_do_unshift(png_row_infop row_info, png_bytep row,
02468     png_const_color_8p sig_bits)
02469 {
02470    int color_type;
02471 
02472    png_debug(1, "in png_do_unshift");
02473 
02474    /* The palette case has already been handled in the _init routine. */
02475    color_type = row_info->color_type;
02476 
02477    if (color_type != PNG_COLOR_TYPE_PALETTE)
02478    {
02479       int shift[4];
02480       int channels = 0;
02481       int bit_depth = row_info->bit_depth;
02482 
02483       if (color_type & PNG_COLOR_MASK_COLOR)
02484       {
02485          shift[channels++] = bit_depth - sig_bits->red;
02486          shift[channels++] = bit_depth - sig_bits->green;
02487          shift[channels++] = bit_depth - sig_bits->blue;
02488       }
02489 
02490       else
02491       {
02492          shift[channels++] = bit_depth - sig_bits->gray;
02493       }
02494 
02495       if (color_type & PNG_COLOR_MASK_ALPHA)
02496       {
02497          shift[channels++] = bit_depth - sig_bits->alpha;
02498       }
02499 
02500       {
02501          int c, have_shift;
02502 
02503          for (c = have_shift = 0; c < channels; ++c)
02504          {
02505             /* A shift of more than the bit depth is an error condition but it
02506              * gets ignored here.
02507              */
02508             if (shift[c] <= 0 || shift[c] >= bit_depth)
02509                shift[c] = 0;
02510 
02511             else
02512                have_shift = 1;
02513          }
02514 
02515          if (!have_shift)
02516             return;
02517       }
02518 
02519       switch (bit_depth)
02520       {
02521          default:
02522          /* Must be 1bpp gray: should not be here! */
02523             /* NOTREACHED */
02524             break;
02525 
02526          case 2:
02527          /* Must be 2bpp gray */
02528          /* assert(channels == 1 && shift[0] == 1) */
02529          {
02530             png_bytep bp = row;
02531             png_bytep bp_end = bp + row_info->rowbytes;
02532 
02533             while (bp < bp_end)
02534             {
02535                int b = (*bp >> 1) & 0x55;
02536                *bp++ = (png_byte)b;
02537             }
02538             break;
02539          }
02540 
02541          case 4:
02542          /* Must be 4bpp gray */
02543          /* assert(channels == 1) */
02544          {
02545             png_bytep bp = row;
02546             png_bytep bp_end = bp + row_info->rowbytes;
02547             int gray_shift = shift[0];
02548             int mask =  0xf >> gray_shift;
02549 
02550             mask |= mask << 4;
02551 
02552             while (bp < bp_end)
02553             {
02554                int b = (*bp >> gray_shift) & mask;
02555                *bp++ = (png_byte)b;
02556             }
02557             break;
02558          }
02559 
02560          case 8:
02561          /* Single byte components, G, GA, RGB, RGBA */
02562          {
02563             png_bytep bp = row;
02564             png_bytep bp_end = bp + row_info->rowbytes;
02565             int channel = 0;
02566 
02567             while (bp < bp_end)
02568             {
02569                int b = *bp >> shift[channel];
02570                if (++channel >= channels)
02571                   channel = 0;
02572                *bp++ = (png_byte)b;
02573             }
02574             break;
02575          }
02576 
02577 #ifdef PNG_READ_16BIT_SUPPORTED
02578          case 16:
02579          /* Double byte components, G, GA, RGB, RGBA */
02580          {
02581             png_bytep bp = row;
02582             png_bytep bp_end = bp + row_info->rowbytes;
02583             int channel = 0;
02584 
02585             while (bp < bp_end)
02586             {
02587                int value = (bp[0] << 8) + bp[1];
02588 
02589                value >>= shift[channel];
02590                if (++channel >= channels)
02591                   channel = 0;
02592                *bp++ = (png_byte)(value >> 8);
02593                *bp++ = (png_byte)(value & 0xff);
02594             }
02595             break;
02596          }
02597 #endif
02598       }
02599    }
02600 }
02601 #endif
02602 
02603 #ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
02604 /* Scale rows of bit depth 16 down to 8 accurately */
02605 void /* PRIVATE */
02606 png_do_scale_16_to_8(png_row_infop row_info, png_bytep row)
02607 {
02608    png_debug(1, "in png_do_scale_16_to_8");
02609 
02610    if (row_info->bit_depth == 16)
02611    {
02612       png_bytep sp = row; /* source */
02613       png_bytep dp = row; /* destination */
02614       png_bytep ep = sp + row_info->rowbytes; /* end+1 */
02615 
02616       while (sp < ep)
02617       {
02618          /* The input is an array of 16 bit components, these must be scaled to
02619           * 8 bits each.  For a 16 bit value V the required value (from the PNG
02620           * specification) is:
02621           *
02622           *    (V * 255) / 65535
02623           *
02624           * This reduces to round(V / 257), or floor((V + 128.5)/257)
02625           *
02626           * Represent V as the two byte value vhi.vlo.  Make a guess that the
02627           * result is the top byte of V, vhi, then the correction to this value
02628           * is:
02629           *
02630           *    error = floor(((V-vhi.vhi) + 128.5) / 257)
02631           *          = floor(((vlo-vhi) + 128.5) / 257)
02632           *
02633           * This can be approximated using integer arithmetic (and a signed
02634           * shift):
02635           *
02636           *    error = (vlo-vhi+128) >> 8;
02637           *
02638           * The approximate differs from the exact answer only when (vlo-vhi) is
02639           * 128; it then gives a correction of +1 when the exact correction is
02640           * 0.  This gives 128 errors.  The exact answer (correct for all 16 bit
02641           * input values) is:
02642           *
02643           *    error = (vlo-vhi+128)*65535 >> 24;
02644           *
02645           * An alternative arithmetic calculation which also gives no errors is:
02646           *
02647           *    (V * 255 + 32895) >> 16
02648           */
02649 
02650          png_int_32 tmp = *sp++; /* must be signed! */
02651          tmp += (((int)*sp++ - tmp + 128) * 65535) >> 24;
02652          *dp++ = (png_byte)tmp;
02653       }
02654 
02655       row_info->bit_depth = 8;
02656       row_info->pixel_depth = (png_byte)(8 * row_info->channels);
02657       row_info->rowbytes = row_info->width * row_info->channels;
02658    }
02659 }
02660 #endif
02661 
02662 #ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
02663 void /* PRIVATE */
02664 /* Simply discard the low byte.  This was the default behavior prior
02665  * to libpng-1.5.4.
02666  */
02667 png_do_chop(png_row_infop row_info, png_bytep row)
02668 {
02669    png_debug(1, "in png_do_chop");
02670 
02671    if (row_info->bit_depth == 16)
02672    {
02673       png_bytep sp = row; /* source */
02674       png_bytep dp = row; /* destination */
02675       png_bytep ep = sp + row_info->rowbytes; /* end+1 */
02676 
02677       while (sp < ep)
02678       {
02679          *dp++ = *sp;
02680          sp += 2; /* skip low byte */
02681       }
02682 
02683       row_info->bit_depth = 8;
02684       row_info->pixel_depth = (png_byte)(8 * row_info->channels);
02685       row_info->rowbytes = row_info->width * row_info->channels;
02686    }
02687 }
02688 #endif
02689 
02690 #ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
02691 void /* PRIVATE */
02692 png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
02693 {
02694    png_debug(1, "in png_do_read_swap_alpha");
02695 
02696    {
02697       png_uint_32 row_width = row_info->width;
02698       if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
02699       {
02700          /* This converts from RGBA to ARGB */
02701          if (row_info->bit_depth == 8)
02702          {
02703             png_bytep sp = row + row_info->rowbytes;
02704             png_bytep dp = sp;
02705             png_byte save;
02706             png_uint_32 i;
02707 
02708             for (i = 0; i < row_width; i++)
02709             {
02710                save = *(--sp);
02711                *(--dp) = *(--sp);
02712                *(--dp) = *(--sp);
02713                *(--dp) = *(--sp);
02714                *(--dp) = save;
02715             }
02716          }
02717 
02718 #ifdef PNG_READ_16BIT_SUPPORTED
02719          /* This converts from RRGGBBAA to AARRGGBB */
02720          else
02721          {
02722             png_bytep sp = row + row_info->rowbytes;
02723             png_bytep dp = sp;
02724             png_byte save[2];
02725             png_uint_32 i;
02726 
02727             for (i = 0; i < row_width; i++)
02728             {
02729                save[0] = *(--sp);
02730                save[1] = *(--sp);
02731                *(--dp) = *(--sp);
02732                *(--dp) = *(--sp);
02733                *(--dp) = *(--sp);
02734                *(--dp) = *(--sp);
02735                *(--dp) = *(--sp);
02736                *(--dp) = *(--sp);
02737                *(--dp) = save[0];
02738                *(--dp) = save[1];
02739             }
02740          }
02741 #endif
02742       }
02743 
02744       else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
02745       {
02746          /* This converts from GA to AG */
02747          if (row_info->bit_depth == 8)
02748          {
02749             png_bytep sp = row + row_info->rowbytes;
02750             png_bytep dp = sp;
02751             png_byte save;
02752             png_uint_32 i;
02753 
02754             for (i = 0; i < row_width; i++)
02755             {
02756                save = *(--sp);
02757                *(--dp) = *(--sp);
02758                *(--dp) = save;
02759             }
02760          }
02761 
02762 #ifdef PNG_READ_16BIT_SUPPORTED
02763          /* This converts from GGAA to AAGG */
02764          else
02765          {
02766             png_bytep sp = row + row_info->rowbytes;
02767             png_bytep dp = sp;
02768             png_byte save[2];
02769             png_uint_32 i;
02770 
02771             for (i = 0; i < row_width; i++)
02772             {
02773                save[0] = *(--sp);
02774                save[1] = *(--sp);
02775                *(--dp) = *(--sp);
02776                *(--dp) = *(--sp);
02777                *(--dp) = save[0];
02778                *(--dp) = save[1];
02779             }
02780          }
02781 #endif
02782       }
02783    }
02784 }
02785 #endif
02786 
02787 #ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
02788 void /* PRIVATE */
02789 png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
02790 {
02791    png_uint_32 row_width;
02792    png_debug(1, "in png_do_read_invert_alpha");
02793 
02794    row_width = row_info->width;
02795    if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
02796    {
02797       if (row_info->bit_depth == 8)
02798       {
02799          /* This inverts the alpha channel in RGBA */
02800          png_bytep sp = row + row_info->rowbytes;
02801          png_bytep dp = sp;
02802          png_uint_32 i;
02803 
02804          for (i = 0; i < row_width; i++)
02805          {
02806             *(--dp) = (png_byte)(255 - *(--sp));
02807 
02808 /*          This does nothing:
02809             *(--dp) = *(--sp);
02810             *(--dp) = *(--sp);
02811             *(--dp) = *(--sp);
02812             We can replace it with:
02813 */
02814             sp-=3;
02815             dp=sp;
02816          }
02817       }
02818 
02819 #ifdef PNG_READ_16BIT_SUPPORTED
02820       /* This inverts the alpha channel in RRGGBBAA */
02821       else
02822       {
02823          png_bytep sp = row + row_info->rowbytes;
02824          png_bytep dp = sp;
02825          png_uint_32 i;
02826 
02827          for (i = 0; i < row_width; i++)
02828          {
02829             *(--dp) = (png_byte)(255 - *(--sp));
02830             *(--dp) = (png_byte)(255 - *(--sp));
02831 
02832 /*          This does nothing:
02833             *(--dp) = *(--sp);
02834             *(--dp) = *(--sp);
02835             *(--dp) = *(--sp);
02836             *(--dp) = *(--sp);
02837             *(--dp) = *(--sp);
02838             *(--dp) = *(--sp);
02839             We can replace it with:
02840 */
02841             sp-=6;
02842             dp=sp;
02843          }
02844       }
02845 #endif
02846    }
02847    else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
02848    {
02849       if (row_info->bit_depth == 8)
02850       {
02851          /* This inverts the alpha channel in GA */
02852          png_bytep sp = row + row_info->rowbytes;
02853          png_bytep dp = sp;
02854          png_uint_32 i;
02855 
02856          for (i = 0; i < row_width; i++)
02857          {
02858             *(--dp) = (png_byte)(255 - *(--sp));
02859             *(--dp) = *(--sp);
02860          }
02861       }
02862 
02863 #ifdef PNG_READ_16BIT_SUPPORTED
02864       else
02865       {
02866          /* This inverts the alpha channel in GGAA */
02867          png_bytep sp  = row + row_info->rowbytes;
02868          png_bytep dp = sp;
02869          png_uint_32 i;
02870 
02871          for (i = 0; i < row_width; i++)
02872          {
02873             *(--dp) = (png_byte)(255 - *(--sp));
02874             *(--dp) = (png_byte)(255 - *(--sp));
02875 /*
02876             *(--dp) = *(--sp);
02877             *(--dp) = *(--sp);
02878 */
02879             sp-=2;
02880             dp=sp;
02881          }
02882       }
02883 #endif
02884    }
02885 }
02886 #endif
02887 
02888 #ifdef PNG_READ_FILLER_SUPPORTED
02889 /* Add filler channel if we have RGB color */
02890 void /* PRIVATE */
02891 png_do_read_filler(png_row_infop row_info, png_bytep row,
02892     png_uint_32 filler, png_uint_32 flags)
02893 {
02894    png_uint_32 i;
02895    png_uint_32 row_width = row_info->width;
02896 
02897 #ifdef PNG_READ_16BIT_SUPPORTED
02898    png_byte hi_filler = (png_byte)((filler>>8) & 0xff);
02899 #endif
02900    png_byte lo_filler = (png_byte)(filler & 0xff);
02901 
02902    png_debug(1, "in png_do_read_filler");
02903 
02904    if (
02905        row_info->color_type == PNG_COLOR_TYPE_GRAY)
02906    {
02907       if (row_info->bit_depth == 8)
02908       {
02909          if (flags & PNG_FLAG_FILLER_AFTER)
02910          {
02911             /* This changes the data from G to GX */
02912             png_bytep sp = row + (png_size_t)row_width;
02913             png_bytep dp =  sp + (png_size_t)row_width;
02914             for (i = 1; i < row_width; i++)
02915             {
02916                *(--dp) = lo_filler;
02917                *(--dp) = *(--sp);
02918             }
02919             *(--dp) = lo_filler;
02920             row_info->channels = 2;
02921             row_info->pixel_depth = 16;
02922             row_info->rowbytes = row_width * 2;
02923          }
02924 
02925          else
02926          {
02927             /* This changes the data from G to XG */
02928             png_bytep sp = row + (png_size_t)row_width;
02929             png_bytep dp = sp  + (png_size_t)row_width;
02930             for (i = 0; i < row_width; i++)
02931             {
02932                *(--dp) = *(--sp);
02933                *(--dp) = lo_filler;
02934             }
02935             row_info->channels = 2;
02936             row_info->pixel_depth = 16;
02937             row_info->rowbytes = row_width * 2;
02938          }
02939       }
02940 
02941 #ifdef PNG_READ_16BIT_SUPPORTED
02942       else if (row_info->bit_depth == 16)
02943       {
02944          if (flags & PNG_FLAG_FILLER_AFTER)
02945          {
02946             /* This changes the data from GG to GGXX */
02947             png_bytep sp = row + (png_size_t)row_width * 2;
02948             png_bytep dp = sp  + (png_size_t)row_width * 2;
02949             for (i = 1; i < row_width; i++)
02950             {
02951                *(--dp) = hi_filler;
02952                *(--dp) = lo_filler;
02953                *(--dp) = *(--sp);
02954                *(--dp) = *(--sp);
02955             }
02956             *(--dp) = hi_filler;
02957             *(--dp) = lo_filler;
02958             row_info->channels = 2;
02959             row_info->pixel_depth = 32;
02960             row_info->rowbytes = row_width * 4;
02961          }
02962 
02963          else
02964          {
02965             /* This changes the data from GG to XXGG */
02966             png_bytep sp = row + (png_size_t)row_width * 2;
02967             png_bytep dp = sp  + (png_size_t)row_width * 2;
02968             for (i = 0; i < row_width; i++)
02969             {
02970                *(--dp) = *(--sp);
02971                *(--dp) = *(--sp);
02972                *(--dp) = hi_filler;
02973                *(--dp) = lo_filler;
02974             }
02975             row_info->channels = 2;
02976             row_info->pixel_depth = 32;
02977             row_info->rowbytes = row_width * 4;
02978          }
02979       }
02980 #endif
02981    } /* COLOR_TYPE == GRAY */
02982    else if (row_info->color_type == PNG_COLOR_TYPE_RGB)
02983    {
02984       if (row_info->bit_depth == 8)
02985       {
02986          if (flags & PNG_FLAG_FILLER_AFTER)
02987          {
02988             /* This changes the data from RGB to RGBX */
02989             png_bytep sp = row + (png_size_t)row_width * 3;
02990             png_bytep dp = sp  + (png_size_t)row_width;
02991             for (i = 1; i < row_width; i++)
02992             {
02993                *(--dp) = lo_filler;
02994                *(--dp) = *(--sp);
02995                *(--dp) = *(--sp);
02996                *(--dp) = *(--sp);
02997             }
02998             *(--dp) = lo_filler;
02999             row_info->channels = 4;
03000             row_info->pixel_depth = 32;
03001             row_info->rowbytes = row_width * 4;
03002          }
03003 
03004          else
03005          {
03006             /* This changes the data from RGB to XRGB */
03007             png_bytep sp = row + (png_size_t)row_width * 3;
03008             png_bytep dp = sp + (png_size_t)row_width;
03009             for (i = 0; i < row_width; i++)
03010             {
03011                *(--dp) = *(--sp);
03012                *(--dp) = *(--sp);
03013                *(--dp) = *(--sp);
03014                *(--dp) = lo_filler;
03015             }
03016             row_info->channels = 4;
03017             row_info->pixel_depth = 32;
03018             row_info->rowbytes = row_width * 4;
03019          }
03020       }
03021 
03022 #ifdef PNG_READ_16BIT_SUPPORTED
03023       else if (row_info->bit_depth == 16)
03024       {
03025          if (flags & PNG_FLAG_FILLER_AFTER)
03026          {
03027             /* This changes the data from RRGGBB to RRGGBBXX */
03028             png_bytep sp = row + (png_size_t)row_width * 6;
03029             png_bytep dp = sp  + (png_size_t)row_width * 2;
03030             for (i = 1; i < row_width; i++)
03031             {
03032                *(--dp) = hi_filler;
03033                *(--dp) = lo_filler;
03034                *(--dp) = *(--sp);
03035                *(--dp) = *(--sp);
03036                *(--dp) = *(--sp);
03037                *(--dp) = *(--sp);
03038                *(--dp) = *(--sp);
03039                *(--dp) = *(--sp);
03040             }
03041             *(--dp) = hi_filler;
03042             *(--dp) = lo_filler;
03043             row_info->channels = 4;
03044             row_info->pixel_depth = 64;
03045             row_info->rowbytes = row_width * 8;
03046          }
03047 
03048          else
03049          {
03050             /* This changes the data from RRGGBB to XXRRGGBB */
03051             png_bytep sp = row + (png_size_t)row_width * 6;
03052             png_bytep dp = sp  + (png_size_t)row_width * 2;
03053             for (i = 0; i < row_width; i++)
03054             {
03055                *(--dp) = *(--sp);
03056                *(--dp) = *(--sp);
03057                *(--dp) = *(--sp);
03058                *(--dp) = *(--sp);
03059                *(--dp) = *(--sp);
03060                *(--dp) = *(--sp);
03061                *(--dp) = hi_filler;
03062                *(--dp) = lo_filler;
03063             }
03064 
03065             row_info->channels = 4;
03066             row_info->pixel_depth = 64;
03067             row_info->rowbytes = row_width * 8;
03068          }
03069       }
03070 #endif
03071    } /* COLOR_TYPE == RGB */
03072 }
03073 #endif
03074 
03075 #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
03076 /* Expand grayscale files to RGB, with or without alpha */
03077 void /* PRIVATE */
03078 png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
03079 {
03080    png_uint_32 i;
03081    png_uint_32 row_width = row_info->width;
03082 
03083    png_debug(1, "in png_do_gray_to_rgb");
03084 
03085    if (row_info->bit_depth >= 8 &&
03086        !(row_info->color_type & PNG_COLOR_MASK_COLOR))
03087    {
03088       if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
03089       {
03090          if (row_info->bit_depth == 8)
03091          {
03092             /* This changes G to RGB */
03093             png_bytep sp = row + (png_size_t)row_width - 1;
03094             png_bytep dp = sp  + (png_size_t)row_width * 2;
03095             for (i = 0; i < row_width; i++)
03096             {
03097                *(dp--) = *sp;
03098                *(dp--) = *sp;
03099                *(dp--) = *(sp--);
03100             }
03101          }
03102 
03103          else
03104          {
03105             /* This changes GG to RRGGBB */
03106             png_bytep sp = row + (png_size_t)row_width * 2 - 1;
03107             png_bytep dp = sp  + (png_size_t)row_width * 4;
03108             for (i = 0; i < row_width; i++)
03109             {
03110                *(dp--) = *sp;
03111                *(dp--) = *(sp - 1);
03112                *(dp--) = *sp;
03113                *(dp--) = *(sp - 1);
03114                *(dp--) = *(sp--);
03115                *(dp--) = *(sp--);
03116             }
03117          }
03118       }
03119 
03120       else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
03121       {
03122          if (row_info->bit_depth == 8)
03123          {
03124             /* This changes GA to RGBA */
03125             png_bytep sp = row + (png_size_t)row_width * 2 - 1;
03126             png_bytep dp = sp  + (png_size_t)row_width * 2;
03127             for (i = 0; i < row_width; i++)
03128             {
03129                *(dp--) = *(sp--);
03130                *(dp--) = *sp;
03131                *(dp--) = *sp;
03132                *(dp--) = *(sp--);
03133             }
03134          }
03135 
03136          else
03137          {
03138             /* This changes GGAA to RRGGBBAA */
03139             png_bytep sp = row + (png_size_t)row_width * 4 - 1;
03140             png_bytep dp = sp  + (png_size_t)row_width * 4;
03141             for (i = 0; i < row_width; i++)
03142             {
03143                *(dp--) = *(sp--);
03144                *(dp--) = *(sp--);
03145                *(dp--) = *sp;
03146                *(dp--) = *(sp - 1);
03147                *(dp--) = *sp;
03148                *(dp--) = *(sp - 1);
03149                *(dp--) = *(sp--);
03150                *(dp--) = *(sp--);
03151             }
03152          }
03153       }
03154       row_info->channels = (png_byte)(row_info->channels + 2);
03155       row_info->color_type |= PNG_COLOR_MASK_COLOR;
03156       row_info->pixel_depth = (png_byte)(row_info->channels *
03157           row_info->bit_depth);
03158       row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
03159    }
03160 }
03161 #endif
03162 
03163 #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
03164 /* Reduce RGB files to grayscale, with or without alpha
03165  * using the equation given in Poynton's ColorFAQ of 1998-01-04 at
03166  * <http://www.inforamp.net/~poynton/>  (THIS LINK IS DEAD June 2008 but
03167  * versions dated 1998 through November 2002 have been archived at
03168  * http://web.archive.org/web/20000816232553/http://www.inforamp.net/
03169  * ~poynton/notes/colour_and_gamma/ColorFAQ.txt )
03170  * Charles Poynton poynton at poynton.com
03171  *
03172  *     Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
03173  *
03174  *  which can be expressed with integers as
03175  *
03176  *     Y = (6969 * R + 23434 * G + 2365 * B)/32768
03177  *
03178  * Poynton's current link (as of January 2003 through July 2011):
03179  * <http://www.poynton.com/notes/colour_and_gamma/>
03180  * has changed the numbers slightly:
03181  *
03182  *     Y = 0.2126*R + 0.7152*G + 0.0722*B
03183  *
03184  *  which can be expressed with integers as
03185  *
03186  *     Y = (6966 * R + 23436 * G + 2366 * B)/32768
03187  *
03188  *  Historically, however, libpng uses numbers derived from the ITU-R Rec 709
03189  *  end point chromaticities and the D65 white point.  Depending on the
03190  *  precision used for the D65 white point this produces a variety of different
03191  *  numbers, however if the four decimal place value used in ITU-R Rec 709 is
03192  *  used (0.3127,0.3290) the Y calculation would be:
03193  *
03194  *     Y = (6968 * R + 23435 * G + 2366 * B)/32768
03195  *
03196  *  While this is correct the rounding results in an overflow for white, because
03197  *  the sum of the rounded coefficients is 32769, not 32768.  Consequently
03198  *  libpng uses, instead, the closest non-overflowing approximation:
03199  *
03200  *     Y = (6968 * R + 23434 * G + 2366 * B)/32768
03201  *
03202  *  Starting with libpng-1.5.5, if the image being converted has a cHRM chunk
03203  *  (including an sRGB chunk) then the chromaticities are used to calculate the
03204  *  coefficients.  See the chunk handling in pngrutil.c for more information.
03205  *
03206  *  In all cases the calculation is to be done in a linear colorspace.  If no
03207  *  gamma information is available to correct the encoding of the original RGB
03208  *  values this results in an implicit assumption that the original PNG RGB
03209  *  values were linear.
03210  *
03211  *  Other integer coefficents can be used via png_set_rgb_to_gray().  Because
03212  *  the API takes just red and green coefficients the blue coefficient is
03213  *  calculated to make the sum 32768.  This will result in different rounding
03214  *  to that used above.
03215  */
03216 int /* PRIVATE */
03217 png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
03218 
03219 {
03220    int rgb_error = 0;
03221 
03222    png_debug(1, "in png_do_rgb_to_gray");
03223 
03224    if (!(row_info->color_type & PNG_COLOR_MASK_PALETTE) &&
03225        (row_info->color_type & PNG_COLOR_MASK_COLOR))
03226    {
03227       PNG_CONST png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff;
03228       PNG_CONST png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff;
03229       PNG_CONST png_uint_32 bc = 32768 - rc - gc;
03230       PNG_CONST png_uint_32 row_width = row_info->width;
03231       PNG_CONST int have_alpha =
03232          (row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0;
03233 
03234       if (row_info->bit_depth == 8)
03235       {
03236 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
03237          /* Notice that gamma to/from 1 are not necessarily inverses (if
03238           * there is an overall gamma correction).  Prior to 1.5.5 this code
03239           * checked the linearized values for equality; this doesn't match
03240           * the documentation, the original values must be checked.
03241           */
03242          if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
03243          {
03244             png_bytep sp = row;
03245             png_bytep dp = row;
03246             png_uint_32 i;
03247 
03248             for (i = 0; i < row_width; i++)
03249             {
03250                png_byte red   = *(sp++);
03251                png_byte green = *(sp++);
03252                png_byte blue  = *(sp++);
03253 
03254                if (red != green || red != blue)
03255                {
03256                   red = png_ptr->gamma_to_1[red];
03257                   green = png_ptr->gamma_to_1[green];
03258                   blue = png_ptr->gamma_to_1[blue];
03259 
03260                   rgb_error |= 1;
03261                   *(dp++) = png_ptr->gamma_from_1[
03262                       (rc*red + gc*green + bc*blue + 16384)>>15];
03263                }
03264 
03265                else
03266                {
03267                   /* If there is no overall correction the table will not be
03268                    * set.
03269                    */
03270                   if (png_ptr->gamma_table != NULL)
03271                      red = png_ptr->gamma_table[red];
03272 
03273                   *(dp++) = red;
03274                }
03275 
03276                if (have_alpha)
03277                   *(dp++) = *(sp++);
03278             }
03279          }
03280          else
03281 #endif
03282          {
03283             png_bytep sp = row;
03284             png_bytep dp = row;
03285             png_uint_32 i;
03286 
03287             for (i = 0; i < row_width; i++)
03288             {
03289                png_byte red   = *(sp++);
03290                png_byte green = *(sp++);
03291                png_byte blue  = *(sp++);
03292 
03293                if (red != green || red != blue)
03294                {
03295                   rgb_error |= 1;
03296                   /*NOTE: this is the historical approach which simply
03297                    * truncates the results.
03298                    */
03299                   *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15);
03300                }
03301 
03302                else
03303                   *(dp++) = red;
03304 
03305                if (have_alpha)
03306                   *(dp++) = *(sp++);
03307             }
03308          }
03309       }
03310 
03311       else /* RGB bit_depth == 16 */
03312       {
03313 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
03314          if (png_ptr->gamma_16_to_1 != NULL && png_ptr->gamma_16_from_1 != NULL)
03315          {
03316             png_bytep sp = row;
03317             png_bytep dp = row;
03318             png_uint_32 i;
03319 
03320             for (i = 0; i < row_width; i++)
03321             {
03322                png_uint_16 red, green, blue, w;
03323 
03324                red   = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
03325                green = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
03326                blue  = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
03327 
03328                if (red == green && red == blue)
03329                {
03330                   if (png_ptr->gamma_16_table != NULL)
03331                      w = png_ptr->gamma_16_table[(red&0xff)
03332                          >> png_ptr->gamma_shift][red>>8];
03333 
03334                   else
03335                      w = red;
03336                }
03337 
03338                else
03339                {
03340                   png_uint_16 red_1   = png_ptr->gamma_16_to_1[(red&0xff)
03341                       >> png_ptr->gamma_shift][red>>8];
03342                   png_uint_16 green_1 =
03343                       png_ptr->gamma_16_to_1[(green&0xff) >>
03344                       png_ptr->gamma_shift][green>>8];
03345                   png_uint_16 blue_1  = png_ptr->gamma_16_to_1[(blue&0xff)
03346                       >> png_ptr->gamma_shift][blue>>8];
03347                   png_uint_16 gray16  = (png_uint_16)((rc*red_1 + gc*green_1
03348                       + bc*blue_1 + 16384)>>15);
03349                   w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
03350                       png_ptr->gamma_shift][gray16 >> 8];
03351                   rgb_error |= 1;
03352                }
03353 
03354                *(dp++) = (png_byte)((w>>8) & 0xff);
03355                *(dp++) = (png_byte)(w & 0xff);
03356 
03357                if (have_alpha)
03358                {
03359                   *(dp++) = *(sp++);
03360                   *(dp++) = *(sp++);
03361                }
03362             }
03363          }
03364          else
03365 #endif
03366          {
03367             png_bytep sp = row;
03368             png_bytep dp = row;
03369             png_uint_32 i;
03370 
03371             for (i = 0; i < row_width; i++)
03372             {
03373                png_uint_16 red, green, blue, gray16;
03374 
03375                red   = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
03376                green = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
03377                blue  = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
03378 
03379                if (red != green || red != blue)
03380                   rgb_error |= 1;
03381 
03382                /* From 1.5.5 in the 16 bit case do the accurate conversion even
03383                 * in the 'fast' case - this is because this is where the code
03384                 * ends up when handling linear 16 bit data.
03385                 */
03386                gray16  = (png_uint_16)((rc*red + gc*green + bc*blue + 16384) >>
03387                   15);
03388                *(dp++) = (png_byte)((gray16>>8) & 0xff);
03389                *(dp++) = (png_byte)(gray16 & 0xff);
03390 
03391                if (have_alpha)
03392                {
03393                   *(dp++) = *(sp++);
03394                   *(dp++) = *(sp++);
03395                }
03396             }
03397          }
03398       }
03399 
03400       row_info->channels = (png_byte)(row_info->channels - 2);
03401       row_info->color_type = (png_byte)(row_info->color_type &
03402           ~PNG_COLOR_MASK_COLOR);
03403       row_info->pixel_depth = (png_byte)(row_info->channels *
03404           row_info->bit_depth);
03405       row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
03406    }
03407    return rgb_error;
03408 }
03409 #endif
03410 #endif /* PNG_READ_TRANSFORMS_SUPPORTED */
03411 
03412 #ifdef PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED
03413 /* Build a grayscale palette.  Palette is assumed to be 1 << bit_depth
03414  * large of png_color.  This lets grayscale images be treated as
03415  * paletted.  Most useful for gamma correction and simplification
03416  * of code.  This API is not used internally.
03417  */
03418 void PNGAPI
03419 png_build_grayscale_palette(int bit_depth, png_colorp palette)
03420 {
03421    int num_palette;
03422    int color_inc;
03423    int i;
03424    int v;
03425 
03426    png_debug(1, "in png_do_build_grayscale_palette");
03427 
03428    if (palette == NULL)
03429       return;
03430 
03431    switch (bit_depth)
03432    {
03433       case 1:
03434          num_palette = 2;
03435          color_inc = 0xff;
03436          break;
03437 
03438       case 2:
03439          num_palette = 4;
03440          color_inc = 0x55;
03441          break;
03442 
03443       case 4:
03444          num_palette = 16;
03445          color_inc = 0x11;
03446          break;
03447 
03448       case 8:
03449          num_palette = 256;
03450          color_inc = 1;
03451          break;
03452 
03453       default:
03454          num_palette = 0;
03455          color_inc = 0;
03456          break;
03457    }
03458 
03459    for (i = 0, v = 0; i < num_palette; i++, v += color_inc)
03460    {
03461       palette[i].red = (png_byte)v;
03462       palette[i].green = (png_byte)v;
03463       palette[i].blue = (png_byte)v;
03464    }
03465 }
03466 #endif
03467 
03468 
03469 #ifdef PNG_READ_TRANSFORMS_SUPPORTED
03470 #if (defined PNG_READ_BACKGROUND_SUPPORTED) ||\
03471    (defined PNG_READ_ALPHA_MODE_SUPPORTED)
03472 /* Replace any alpha or transparency with the supplied background color.
03473  * "background" is already in the screen gamma, while "background_1" is
03474  * at a gamma of 1.0.  Paletted files have already been taken care of.
03475  */
03476 void /* PRIVATE */
03477 png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
03478 {
03479 #ifdef PNG_READ_GAMMA_SUPPORTED
03480    png_const_bytep gamma_table = png_ptr->gamma_table;
03481    png_const_bytep gamma_from_1 = png_ptr->gamma_from_1;
03482    png_const_bytep gamma_to_1 = png_ptr->gamma_to_1;
03483    png_const_uint_16pp gamma_16 = png_ptr->gamma_16_table;
03484    png_const_uint_16pp gamma_16_from_1 = png_ptr->gamma_16_from_1;
03485    png_const_uint_16pp gamma_16_to_1 = png_ptr->gamma_16_to_1;
03486    int gamma_shift = png_ptr->gamma_shift;
03487 #endif
03488 
03489    png_bytep sp;
03490    png_uint_32 i;
03491    png_uint_32 row_width = row_info->width;
03492    int optimize = (png_ptr->flags & PNG_FLAG_OPTIMIZE_ALPHA) != 0;
03493    int shift;
03494 
03495    png_debug(1, "in png_do_compose");
03496 
03497    {
03498       switch (row_info->color_type)
03499       {
03500          case PNG_COLOR_TYPE_GRAY:
03501          {
03502             switch (row_info->bit_depth)
03503             {
03504                case 1:
03505                {
03506                   sp = row;
03507                   shift = 7;
03508                   for (i = 0; i < row_width; i++)
03509                   {
03510                      if ((png_uint_16)((*sp >> shift) & 0x01)
03511                         == png_ptr->trans_color.gray)
03512                      {
03513                         *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
03514                         *sp |= (png_byte)(png_ptr->background.gray << shift);
03515                      }
03516 
03517                      if (!shift)
03518                      {
03519                         shift = 7;
03520                         sp++;
03521                      }
03522 
03523                      else
03524                         shift--;
03525                   }
03526                   break;
03527                }
03528 
03529                case 2:
03530                {
03531 #ifdef PNG_READ_GAMMA_SUPPORTED
03532                   if (gamma_table != NULL)
03533                   {
03534                      sp = row;
03535                      shift = 6;
03536                      for (i = 0; i < row_width; i++)
03537                      {
03538                         if ((png_uint_16)((*sp >> shift) & 0x03)
03539                             == png_ptr->trans_color.gray)
03540                         {
03541                            *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
03542                            *sp |= (png_byte)(png_ptr->background.gray << shift);
03543                         }
03544 
03545                         else
03546                         {
03547                            png_byte p = (png_byte)((*sp >> shift) & 0x03);
03548                            png_byte g = (png_byte)((gamma_table [p | (p << 2) |
03549                                (p << 4) | (p << 6)] >> 6) & 0x03);
03550                            *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
03551                            *sp |= (png_byte)(g << shift);
03552                         }
03553 
03554                         if (!shift)
03555                         {
03556                            shift = 6;
03557                            sp++;
03558                         }
03559 
03560                         else
03561                            shift -= 2;
03562                      }
03563                   }
03564 
03565                   else
03566 #endif
03567                   {
03568                      sp = row;
03569                      shift = 6;
03570                      for (i = 0; i < row_width; i++)
03571                      {
03572                         if ((png_uint_16)((*sp >> shift) & 0x03)
03573                             == png_ptr->trans_color.gray)
03574                         {
03575                            *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
03576                            *sp |= (png_byte)(png_ptr->background.gray << shift);
03577                         }
03578 
03579                         if (!shift)
03580                         {
03581                            shift = 6;
03582                            sp++;
03583                         }
03584 
03585                         else
03586                            shift -= 2;
03587                      }
03588                   }
03589                   break;
03590                }
03591 
03592                case 4:
03593                {
03594 #ifdef PNG_READ_GAMMA_SUPPORTED
03595                   if (gamma_table != NULL)
03596                   {
03597                      sp = row;
03598                      shift = 4;
03599                      for (i = 0; i < row_width; i++)
03600                      {
03601                         if ((png_uint_16)((*sp >> shift) & 0x0f)
03602                             == png_ptr->trans_color.gray)
03603                         {
03604                            *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
03605                            *sp |= (png_byte)(png_ptr->background.gray << shift);
03606                         }
03607 
03608                         else
03609                         {
03610                            png_byte p = (png_byte)((*sp >> shift) & 0x0f);
03611                            png_byte g = (png_byte)((gamma_table[p |
03612                                (p << 4)] >> 4) & 0x0f);
03613                            *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
03614                            *sp |= (png_byte)(g << shift);
03615                         }
03616 
03617                         if (!shift)
03618                         {
03619                            shift = 4;
03620                            sp++;
03621                         }
03622 
03623                         else
03624                            shift -= 4;
03625                      }
03626                   }
03627 
03628                   else
03629 #endif
03630                   {
03631                      sp = row;
03632                      shift = 4;
03633                      for (i = 0; i < row_width; i++)
03634                      {
03635                         if ((png_uint_16)((*sp >> shift) & 0x0f)
03636                             == png_ptr->trans_color.gray)
03637                         {
03638                            *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
03639                            *sp |= (png_byte)(png_ptr->background.gray << shift);
03640                         }
03641 
03642                         if (!shift)
03643                         {
03644                            shift = 4;
03645                            sp++;
03646                         }
03647 
03648                         else
03649                            shift -= 4;
03650                      }
03651                   }
03652                   break;
03653                }
03654 
03655                case 8:
03656                {
03657 #ifdef PNG_READ_GAMMA_SUPPORTED
03658                   if (gamma_table != NULL)
03659                   {
03660                      sp = row;
03661                      for (i = 0; i < row_width; i++, sp++)
03662                      {
03663                         if (*sp == png_ptr->trans_color.gray)
03664                            *sp = (png_byte)png_ptr->background.gray;
03665 
03666                         else
03667                            *sp = gamma_table[*sp];
03668                      }
03669                   }
03670                   else
03671 #endif
03672                   {
03673                      sp = row;
03674                      for (i = 0; i < row_width; i++, sp++)
03675                      {
03676                         if (*sp == png_ptr->trans_color.gray)
03677                            *sp = (png_byte)png_ptr->background.gray;
03678                      }
03679                   }
03680                   break;
03681                }
03682 
03683                case 16:
03684                {
03685 #ifdef PNG_READ_GAMMA_SUPPORTED
03686                   if (gamma_16 != NULL)
03687                   {
03688                      sp = row;
03689                      for (i = 0; i < row_width; i++, sp += 2)
03690                      {
03691                         png_uint_16 v;
03692 
03693                         v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
03694 
03695                         if (v == png_ptr->trans_color.gray)
03696                         {
03697                            /* Background is already in screen gamma */
03698                            *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
03699                            *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
03700                         }
03701 
03702                         else
03703                         {
03704                            v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
03705                            *sp = (png_byte)((v >> 8) & 0xff);
03706                            *(sp + 1) = (png_byte)(v & 0xff);
03707                         }
03708                      }
03709                   }
03710                   else
03711 #endif
03712                   {
03713                      sp = row;
03714                      for (i = 0; i < row_width; i++, sp += 2)
03715                      {
03716                         png_uint_16 v;
03717 
03718                         v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
03719 
03720                         if (v == png_ptr->trans_color.gray)
03721                         {
03722                            *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
03723                            *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
03724                         }
03725                      }
03726                   }
03727                   break;
03728                }
03729 
03730                default:
03731                   break;
03732             }
03733             break;
03734          }
03735 
03736          case PNG_COLOR_TYPE_RGB:
03737          {
03738             if (row_info->bit_depth == 8)
03739             {
03740 #ifdef PNG_READ_GAMMA_SUPPORTED
03741                if (gamma_table != NULL)
03742                {
03743                   sp = row;
03744                   for (i = 0; i < row_width; i++, sp += 3)
03745                   {
03746                      if (*sp == png_ptr->trans_color.red &&
03747                          *(sp + 1) == png_ptr->trans_color.green &&
03748                          *(sp + 2) == png_ptr->trans_color.blue)
03749                      {
03750                         *sp = (png_byte)png_ptr->background.red;
03751                         *(sp + 1) = (png_byte)png_ptr->background.green;
03752                         *(sp + 2) = (png_byte)png_ptr->background.blue;
03753                      }
03754 
03755                      else
03756                      {
03757                         *sp = gamma_table[*sp];
03758                         *(sp + 1) = gamma_table[*(sp + 1)];
03759                         *(sp + 2) = gamma_table[*(sp + 2)];
03760                      }
03761                   }
03762                }
03763                else
03764 #endif
03765                {
03766                   sp = row;
03767                   for (i = 0; i < row_width; i++, sp += 3)
03768                   {
03769                      if (*sp == png_ptr->trans_color.red &&
03770                          *(sp + 1) == png_ptr->trans_color.green &&
03771                          *(sp + 2) == png_ptr->trans_color.blue)
03772                      {
03773                         *sp = (png_byte)png_ptr->background.red;
03774                         *(sp + 1) = (png_byte)png_ptr->background.green;
03775                         *(sp + 2) = (png_byte)png_ptr->background.blue;
03776                      }
03777                   }
03778                }
03779             }
03780             else /* if (row_info->bit_depth == 16) */
03781             {
03782 #ifdef PNG_READ_GAMMA_SUPPORTED
03783                if (gamma_16 != NULL)
03784                {
03785                   sp = row;
03786                   for (i = 0; i < row_width; i++, sp += 6)
03787                   {
03788                      png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
03789 
03790                      png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
03791                          + *(sp + 3));
03792 
03793                      png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
03794                          + *(sp + 5));
03795 
03796                      if (r == png_ptr->trans_color.red &&
03797                          g == png_ptr->trans_color.green &&
03798                          b == png_ptr->trans_color.blue)
03799                      {
03800                         /* Background is already in screen gamma */
03801                         *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
03802                         *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
03803                         *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff);
03804                         *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff);
03805                         *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff);
03806                         *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
03807                      }
03808 
03809                      else
03810                      {
03811                         png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
03812                         *sp = (png_byte)((v >> 8) & 0xff);
03813                         *(sp + 1) = (png_byte)(v & 0xff);
03814 
03815                         v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
03816                         *(sp + 2) = (png_byte)((v >> 8) & 0xff);
03817                         *(sp + 3) = (png_byte)(v & 0xff);
03818 
03819                         v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
03820                         *(sp + 4) = (png_byte)((v >> 8) & 0xff);
03821                         *(sp + 5) = (png_byte)(v & 0xff);
03822                      }
03823                   }
03824                }
03825 
03826                else
03827 #endif
03828                {
03829                   sp = row;
03830                   for (i = 0; i < row_width; i++, sp += 6)
03831                   {
03832                      png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
03833 
03834                      png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
03835                          + *(sp + 3));
03836 
03837                      png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
03838                          + *(sp + 5));
03839 
03840                      if (r == png_ptr->trans_color.red &&
03841                          g == png_ptr->trans_color.green &&
03842                          b == png_ptr->trans_color.blue)
03843                      {
03844                         *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
03845                         *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
03846                         *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff);
03847                         *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff);
03848                         *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff);
03849                         *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
03850                      }
03851                   }
03852                }
03853             }
03854             break;
03855          }
03856 
03857          case PNG_COLOR_TYPE_GRAY_ALPHA:
03858          {
03859             if (row_info->bit_depth == 8)
03860             {
03861 #ifdef PNG_READ_GAMMA_SUPPORTED
03862                if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
03863                    gamma_table != NULL)
03864                {
03865                   sp = row;
03866                   for (i = 0; i < row_width; i++, sp += 2)
03867                   {
03868                      png_uint_16 a = *(sp + 1);
03869 
03870                      if (a == 0xff)
03871                         *sp = gamma_table[*sp];
03872 
03873                      else if (a == 0)
03874                      {
03875                         /* Background is already in screen gamma */
03876                         *sp = (png_byte)png_ptr->background.gray;
03877                      }
03878 
03879                      else
03880                      {
03881                         png_byte v, w;
03882 
03883                         v = gamma_to_1[*sp];
03884                         png_composite(w, v, a, png_ptr->background_1.gray);
03885                         if (!optimize)
03886                            w = gamma_from_1[w];
03887                         *sp = w;
03888                      }
03889                   }
03890                }
03891                else
03892 #endif
03893                {
03894                   sp = row;
03895                   for (i = 0; i < row_width; i++, sp += 2)
03896                   {
03897                      png_byte a = *(sp + 1);
03898 
03899                      if (a == 0)
03900                         *sp = (png_byte)png_ptr->background.gray;
03901 
03902                      else if (a < 0xff)
03903                         png_composite(*sp, *sp, a, png_ptr->background_1.gray);
03904                   }
03905                }
03906             }
03907             else /* if (png_ptr->bit_depth == 16) */
03908             {
03909 #ifdef PNG_READ_GAMMA_SUPPORTED
03910                if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
03911                    gamma_16_to_1 != NULL)
03912                {
03913                   sp = row;
03914                   for (i = 0; i < row_width; i++, sp += 4)
03915                   {
03916                      png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8)
03917                          + *(sp + 3));
03918 
03919                      if (a == (png_uint_16)0xffff)
03920                      {
03921                         png_uint_16 v;
03922 
03923                         v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
03924                         *sp = (png_byte)((v >> 8) & 0xff);
03925                         *(sp + 1) = (png_byte)(v & 0xff);
03926                      }
03927 
03928                      else if (a == 0)
03929                      {
03930                         /* Background is already in screen gamma */
03931                         *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
03932                         *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
03933                      }
03934 
03935                      else
03936                      {
03937                         png_uint_16 g, v, w;
03938 
03939                         g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
03940                         png_composite_16(v, g, a, png_ptr->background_1.gray);
03941                         if (optimize)
03942                            w = v;
03943                         else
03944                            w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8];
03945                         *sp = (png_byte)((w >> 8) & 0xff);
03946                         *(sp + 1) = (png_byte)(w & 0xff);
03947                      }
03948                   }
03949                }
03950                else
03951 #endif
03952                {
03953                   sp = row;
03954                   for (i = 0; i < row_width; i++, sp += 4)
03955                   {
03956                      png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8)
03957                          + *(sp + 3));
03958 
03959                      if (a == 0)
03960                      {
03961                         *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
03962                         *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
03963                      }
03964 
03965                      else if (a < 0xffff)
03966                      {
03967                         png_uint_16 g, v;
03968 
03969                         g = (png_uint_16)(((*sp) << 8) + *(sp + 1));
03970                         png_composite_16(v, g, a, png_ptr->background_1.gray);
03971                         *sp = (png_byte)((v >> 8) & 0xff);
03972                         *(sp + 1) = (png_byte)(v & 0xff);
03973                      }
03974                   }
03975                }
03976             }
03977             break;
03978          }
03979 
03980          case PNG_COLOR_TYPE_RGB_ALPHA:
03981          {
03982             if (row_info->bit_depth == 8)
03983             {
03984 #ifdef PNG_READ_GAMMA_SUPPORTED
03985                if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
03986                    gamma_table != NULL)
03987                {
03988                   sp = row;
03989                   for (i = 0; i < row_width; i++, sp += 4)
03990                   {
03991                      png_byte a = *(sp + 3);
03992 
03993                      if (a == 0xff)
03994                      {
03995                         *sp = gamma_table[*sp];
03996                         *(sp + 1) = gamma_table[*(sp + 1)];
03997                         *(sp + 2) = gamma_table[*(sp + 2)];
03998                      }
03999 
04000                      else if (a == 0)
04001                      {
04002                         /* Background is already in screen gamma */
04003                         *sp = (png_byte)png_ptr->background.red;
04004                         *(sp + 1) = (png_byte)png_ptr->background.green;
04005                         *(sp + 2) = (png_byte)png_ptr->background.blue;
04006                      }
04007 
04008                      else
04009                      {
04010                         png_byte v, w;
04011 
04012                         v = gamma_to_1[*sp];
04013                         png_composite(w, v, a, png_ptr->background_1.red);
04014                         if (!optimize) w = gamma_from_1[w];
04015                         *sp = w;
04016 
04017                         v = gamma_to_1[*(sp + 1)];
04018                         png_composite(w, v, a, png_ptr->background_1.green);
04019                         if (!optimize) w = gamma_from_1[w];
04020                         *(sp + 1) = w;
04021 
04022                         v = gamma_to_1[*(sp + 2)];
04023                         png_composite(w, v, a, png_ptr->background_1.blue);
04024                         if (!optimize) w = gamma_from_1[w];
04025                         *(sp + 2) = w;
04026                      }
04027                   }
04028                }
04029                else
04030 #endif
04031                {
04032                   sp = row;
04033                   for (i = 0; i < row_width; i++, sp += 4)
04034                   {
04035                      png_byte a = *(sp + 3);
04036 
04037                      if (a == 0)
04038                      {
04039                         *sp = (png_byte)png_ptr->background.red;
04040                         *(sp + 1) = (png_byte)png_ptr->background.green;
04041                         *(sp + 2) = (png_byte)png_ptr->background.blue;
04042                      }
04043 
04044                      else if (a < 0xff)
04045                      {
04046                         png_composite(*sp, *sp, a, png_ptr->background.red);
04047 
04048                         png_composite(*(sp + 1), *(sp + 1), a,
04049                             png_ptr->background.green);
04050 
04051                         png_composite(*(sp + 2), *(sp + 2), a,
04052                             png_ptr->background.blue);
04053                      }
04054                   }
04055                }
04056             }
04057             else /* if (row_info->bit_depth == 16) */
04058             {
04059 #ifdef PNG_READ_GAMMA_SUPPORTED
04060                if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
04061                    gamma_16_to_1 != NULL)
04062                {
04063                   sp = row;
04064                   for (i = 0; i < row_width; i++, sp += 8)
04065                   {
04066                      png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
04067                          << 8) + (png_uint_16)(*(sp + 7)));
04068 
04069                      if (a == (png_uint_16)0xffff)
04070                      {
04071                         png_uint_16 v;
04072 
04073                         v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
04074                         *sp = (png_byte)((v >> 8) & 0xff);
04075                         *(sp + 1) = (png_byte)(v & 0xff);
04076 
04077                         v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
04078                         *(sp + 2) = (png_byte)((v >> 8) & 0xff);
04079                         *(sp + 3) = (png_byte)(v & 0xff);
04080 
04081                         v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
04082                         *(sp + 4) = (png_byte)((v >> 8) & 0xff);
04083                         *(sp + 5) = (png_byte)(v & 0xff);
04084                      }
04085 
04086                      else if (a == 0)
04087                      {
04088                         /* Background is already in screen gamma */
04089                         *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
04090                         *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
04091                         *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff);
04092                         *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff);
04093                         *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff);
04094                         *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
04095                      }
04096 
04097                      else
04098                      {
04099                         png_uint_16 v, w;
04100 
04101                         v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
04102                         png_composite_16(w, v, a, png_ptr->background_1.red);
04103                         if (!optimize)
04104                            w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
04105                         *sp = (png_byte)((w >> 8) & 0xff);
04106                         *(sp + 1) = (png_byte)(w & 0xff);
04107 
04108                         v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)];
04109                         png_composite_16(w, v, a, png_ptr->background_1.green);
04110                         if (!optimize)
04111                            w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
04112 
04113                         *(sp + 2) = (png_byte)((w >> 8) & 0xff);
04114                         *(sp + 3) = (png_byte)(w & 0xff);
04115 
04116                         v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)];
04117                         png_composite_16(w, v, a, png_ptr->background_1.blue);
04118                         if (!optimize)
04119                            w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
04120 
04121                         *(sp + 4) = (png_byte)((w >> 8) & 0xff);
04122                         *(sp + 5) = (png_byte)(w & 0xff);
04123                      }
04124                   }
04125                }
04126 
04127                else
04128 #endif
04129                {
04130                   sp = row;
04131                   for (i = 0; i < row_width; i++, sp += 8)
04132                   {
04133                      png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
04134                          << 8) + (png_uint_16)(*(sp + 7)));
04135 
04136                      if (a == 0)
04137                      {
04138                         *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
04139                         *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
04140                         *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff);
04141                         *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff);
04142                         *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff);
04143                         *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
04144                      }
04145 
04146                      else if (a < 0xffff)
04147                      {
04148                         png_uint_16 v;
04149 
04150                         png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
04151                         png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
04152                             + *(sp + 3));
04153                         png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
04154                             + *(sp + 5));
04155 
04156                         png_composite_16(v, r, a, png_ptr->background.red);
04157                         *sp = (png_byte)((v >> 8) & 0xff);
04158                         *(sp + 1) = (png_byte)(v & 0xff);
04159 
04160                         png_composite_16(v, g, a, png_ptr->background.green);
04161                         *(sp + 2) = (png_byte)((v >> 8) & 0xff);
04162                         *(sp + 3) = (png_byte)(v & 0xff);
04163 
04164                         png_composite_16(v, b, a, png_ptr->background.blue);
04165                         *(sp + 4) = (png_byte)((v >> 8) & 0xff);
04166                         *(sp + 5) = (png_byte)(v & 0xff);
04167                      }
04168                   }
04169                }
04170             }
04171             break;
04172          }
04173 
04174          default:
04175             break;
04176       }
04177    }
04178 }
04179 #endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_READ_ALPHA_MODE_SUPPORTED */
04180 
04181 #ifdef PNG_READ_GAMMA_SUPPORTED
04182 /* Gamma correct the image, avoiding the alpha channel.  Make sure
04183  * you do this after you deal with the transparency issue on grayscale
04184  * or RGB images. If your bit depth is 8, use gamma_table, if it
04185  * is 16, use gamma_16_table and gamma_shift.  Build these with
04186  * build_gamma_table().
04187  */
04188 void /* PRIVATE */
04189 png_do_gamma(png_row_infop row_info, png_bytep row, png_structp png_ptr)
04190 {
04191    png_const_bytep gamma_table = png_ptr->gamma_table;
04192    png_const_uint_16pp gamma_16_table = png_ptr->gamma_16_table;
04193    int gamma_shift = png_ptr->gamma_shift;
04194 
04195    png_bytep sp;
04196    png_uint_32 i;
04197    png_uint_32 row_width=row_info->width;
04198 
04199    png_debug(1, "in png_do_gamma");
04200 
04201    if (((row_info->bit_depth <= 8 && gamma_table != NULL) ||
04202        (row_info->bit_depth == 16 && gamma_16_table != NULL)))
04203    {
04204       switch (row_info->color_type)
04205       {
04206          case PNG_COLOR_TYPE_RGB:
04207          {
04208             if (row_info->bit_depth == 8)
04209             {
04210                sp = row;
04211                for (i = 0; i < row_width; i++)
04212                {
04213                   *sp = gamma_table[*sp];
04214                   sp++;
04215                   *sp = gamma_table[*sp];
04216                   sp++;
04217                   *sp = gamma_table[*sp];
04218                   sp++;
04219                }
04220             }
04221 
04222             else /* if (row_info->bit_depth == 16) */
04223             {
04224                sp = row;
04225                for (i = 0; i < row_width; i++)
04226                {
04227                   png_uint_16 v;
04228 
04229                   v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
04230                   *sp = (png_byte)((v >> 8) & 0xff);
04231                   *(sp + 1) = (png_byte)(v & 0xff);
04232                   sp += 2;
04233 
04234                   v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
04235                   *sp = (png_byte)((v >> 8) & 0xff);
04236                   *(sp + 1) = (png_byte)(v & 0xff);
04237                   sp += 2;
04238 
04239                   v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
04240                   *sp = (png_byte)((v >> 8) & 0xff);
04241                   *(sp + 1) = (png_byte)(v & 0xff);
04242                   sp += 2;
04243                }
04244             }
04245             break;
04246          }
04247 
04248          case PNG_COLOR_TYPE_RGB_ALPHA:
04249          {
04250             if (row_info->bit_depth == 8)
04251             {
04252                sp = row;
04253                for (i = 0; i < row_width; i++)
04254                {
04255                   *sp = gamma_table[*sp];
04256                   sp++;
04257 
04258                   *sp = gamma_table[*sp];
04259                   sp++;
04260 
04261                   *sp = gamma_table[*sp];
04262                   sp++;
04263 
04264                   sp++;
04265                }
04266             }
04267 
04268             else /* if (row_info->bit_depth == 16) */
04269             {
04270                sp = row;
04271                for (i = 0; i < row_width; i++)
04272                {
04273                   png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
04274                   *sp = (png_byte)((v >> 8) & 0xff);
04275                   *(sp + 1) = (png_byte)(v & 0xff);
04276                   sp += 2;
04277 
04278                   v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
04279                   *sp = (png_byte)((v >> 8) & 0xff);
04280                   *(sp + 1) = (png_byte)(v & 0xff);
04281                   sp += 2;
04282 
04283                   v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
04284                   *sp = (png_byte)((v >> 8) & 0xff);
04285                   *(sp + 1) = (png_byte)(v & 0xff);
04286                   sp += 4;
04287                }
04288             }
04289             break;
04290          }
04291 
04292          case PNG_COLOR_TYPE_GRAY_ALPHA:
04293          {
04294             if (row_info->bit_depth == 8)
04295             {
04296                sp = row;
04297                for (i = 0; i < row_width; i++)
04298                {
04299                   *sp = gamma_table[*sp];
04300                   sp += 2;
04301                }
04302             }
04303 
04304             else /* if (row_info->bit_depth == 16) */
04305             {
04306                sp = row;
04307                for (i = 0; i < row_width; i++)
04308                {
04309                   png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
04310                   *sp = (png_byte)((v >> 8) & 0xff);
04311                   *(sp + 1) = (png_byte)(v & 0xff);
04312                   sp += 4;
04313                }
04314             }
04315             break;
04316          }
04317 
04318          case PNG_COLOR_TYPE_GRAY:
04319          {
04320             if (row_info->bit_depth == 2)
04321             {
04322                sp = row;
04323                for (i = 0; i < row_width; i += 4)
04324                {
04325                   int a = *sp & 0xc0;
04326                   int b = *sp & 0x30;
04327                   int c = *sp & 0x0c;
04328                   int d = *sp & 0x03;
04329 
04330                   *sp = (png_byte)(
04331                       ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)])   ) & 0xc0)|
04332                       ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)|
04333                       ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)|
04334                       ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) ));
04335                   sp++;
04336                }
04337             }
04338 
04339             if (row_info->bit_depth == 4)
04340             {
04341                sp = row;
04342                for (i = 0; i < row_width; i += 2)
04343                {
04344                   int msb = *sp & 0xf0;
04345                   int lsb = *sp & 0x0f;
04346 
04347                   *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0)
04348                       | (((int)gamma_table[(lsb << 4) | lsb]) >> 4));
04349                   sp++;
04350                }
04351             }
04352 
04353             else if (row_info->bit_depth == 8)
04354             {
04355                sp = row;
04356                for (i = 0; i < row_width; i++)
04357                {
04358                   *sp = gamma_table[*sp];
04359                   sp++;
04360                }
04361             }
04362 
04363             else if (row_info->bit_depth == 16)
04364             {
04365                sp = row;
04366                for (i = 0; i < row_width; i++)
04367                {
04368                   png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
04369                   *sp = (png_byte)((v >> 8) & 0xff);
04370                   *(sp + 1) = (png_byte)(v & 0xff);
04371                   sp += 2;
04372                }
04373             }
04374             break;
04375          }
04376 
04377          default:
04378             break;
04379       }
04380    }
04381 }
04382 #endif
04383 
04384 #ifdef PNG_READ_ALPHA_MODE_SUPPORTED
04385 /* Encode the alpha channel to the output gamma (the input channel is always
04386  * linear.)  Called only with color types that have an alpha channel.  Needs the
04387  * from_1 tables.
04388  */
04389 void /* PRIVATE */
04390 png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structp png_ptr)
04391 {
04392    png_uint_32 row_width = row_info->width;
04393 
04394    png_debug(1, "in png_do_encode_alpha");
04395 
04396    if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
04397    {
04398       if (row_info->bit_depth == 8)
04399       {
04400          PNG_CONST png_bytep table = png_ptr->gamma_from_1;
04401 
04402          if (table != NULL)
04403          {
04404             PNG_CONST int step =
04405                (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 4 : 2;
04406 
04407             /* The alpha channel is the last component: */
04408             row += step - 1;
04409 
04410             for (; row_width > 0; --row_width, row += step)
04411                *row = table[*row];
04412 
04413             return;
04414          }
04415       }
04416 
04417       else if (row_info->bit_depth == 16)
04418       {
04419          PNG_CONST png_uint_16pp table = png_ptr->gamma_16_from_1;
04420          PNG_CONST int gamma_shift = png_ptr->gamma_shift;
04421 
04422          if (table != NULL)
04423          {
04424             PNG_CONST int step =
04425                (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 8 : 4;
04426 
04427             /* The alpha channel is the last component: */
04428             row += step - 2;
04429 
04430             for (; row_width > 0; --row_width, row += step)
04431             {
04432                png_uint_16 v;
04433 
04434                v = table[*(row + 1) >> gamma_shift][*row];
04435                *row = (png_byte)((v >> 8) & 0xff);
04436                *(row + 1) = (png_byte)(v & 0xff);
04437             }
04438 
04439             return;
04440          }
04441       }
04442    }
04443 
04444    /* Only get to here if called with a weird row_info; no harm has been done,
04445     * so just issue a warning.
04446     */
04447    png_warning(png_ptr, "png_do_encode_alpha: unexpected call");
04448 }
04449 #endif
04450 
04451 #ifdef PNG_READ_EXPAND_SUPPORTED
04452 /* Expands a palette row to an RGB or RGBA row depending
04453  * upon whether you supply trans and num_trans.
04454  */
04455 void /* PRIVATE */
04456 png_do_expand_palette(png_row_infop row_info, png_bytep row,
04457    png_const_colorp palette, png_const_bytep trans_alpha, int num_trans)
04458 {
04459    int shift, value;
04460    png_bytep sp, dp;
04461    png_uint_32 i;
04462    png_uint_32 row_width=row_info->width;
04463 
04464    png_debug(1, "in png_do_expand_palette");
04465 
04466    if (row_info->color_type == PNG_COLOR_TYPE_PALETTE)
04467    {
04468       if (row_info->bit_depth < 8)
04469       {
04470          switch (row_info->bit_depth)
04471          {
04472             case 1:
04473             {
04474                sp = row + (png_size_t)((row_width - 1) >> 3);
04475                dp = row + (png_size_t)row_width - 1;
04476                shift = 7 - (int)((row_width + 7) & 0x07);
04477                for (i = 0; i < row_width; i++)
04478                {
04479                   if ((*sp >> shift) & 0x01)
04480                      *dp = 1;
04481 
04482                   else
04483                      *dp = 0;
04484 
04485                   if (shift == 7)
04486                   {
04487                      shift = 0;
04488                      sp--;
04489                   }
04490 
04491                   else
04492                      shift++;
04493 
04494                   dp--;
04495                }
04496                break;
04497             }
04498 
04499             case 2:
04500             {
04501                sp = row + (png_size_t)((row_width - 1) >> 2);
04502                dp = row + (png_size_t)row_width - 1;
04503                shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
04504                for (i = 0; i < row_width; i++)
04505                {
04506                   value = (*sp >> shift) & 0x03;
04507                   *dp = (png_byte)value;
04508                   if (shift == 6)
04509                   {
04510                      shift = 0;
04511                      sp--;
04512                   }
04513 
04514                   else
04515                      shift += 2;
04516 
04517                   dp--;
04518                }
04519                break;
04520             }
04521 
04522             case 4:
04523             {
04524                sp = row + (png_size_t)((row_width - 1) >> 1);
04525                dp = row + (png_size_t)row_width - 1;
04526                shift = (int)((row_width & 0x01) << 2);
04527                for (i = 0; i < row_width; i++)
04528                {
04529                   value = (*sp >> shift) & 0x0f;
04530                   *dp = (png_byte)value;
04531                   if (shift == 4)
04532                   {
04533                      shift = 0;
04534                      sp--;
04535                   }
04536 
04537                   else
04538                      shift += 4;
04539 
04540                   dp--;
04541                }
04542                break;
04543             }
04544 
04545             default:
04546                break;
04547          }
04548          row_info->bit_depth = 8;
04549          row_info->pixel_depth = 8;
04550          row_info->rowbytes = row_width;
04551       }
04552 
04553       if (row_info->bit_depth == 8)
04554       {
04555          {
04556             if (num_trans > 0)
04557             {
04558                sp = row + (png_size_t)row_width - 1;
04559                dp = row + (png_size_t)(row_width << 2) - 1;
04560 
04561                for (i = 0; i < row_width; i++)
04562                {
04563                   if ((int)(*sp) >= num_trans)
04564                      *dp-- = 0xff;
04565 
04566                   else
04567                      *dp-- = trans_alpha[*sp];
04568 
04569                   *dp-- = palette[*sp].blue;
04570                   *dp-- = palette[*sp].green;
04571                   *dp-- = palette[*sp].red;
04572                   sp--;
04573                }
04574                row_info->bit_depth = 8;
04575                row_info->pixel_depth = 32;
04576                row_info->rowbytes = row_width * 4;
04577                row_info->color_type = 6;
04578                row_info->channels = 4;
04579             }
04580 
04581             else
04582             {
04583                sp = row + (png_size_t)row_width - 1;
04584                dp = row + (png_size_t)(row_width * 3) - 1;
04585 
04586                for (i = 0; i < row_width; i++)
04587                {
04588                   *dp-- = palette[*sp].blue;
04589                   *dp-- = palette[*sp].green;
04590                   *dp-- = palette[*sp].red;
04591                   sp--;
04592                }
04593 
04594                row_info->bit_depth = 8;
04595                row_info->pixel_depth = 24;
04596                row_info->rowbytes = row_width * 3;
04597                row_info->color_type = 2;
04598                row_info->channels = 3;
04599             }
04600          }
04601       }
04602    }
04603 }
04604 
04605 /* If the bit depth < 8, it is expanded to 8.  Also, if the already
04606  * expanded transparency value is supplied, an alpha channel is built.
04607  */
04608 void /* PRIVATE */
04609 png_do_expand(png_row_infop row_info, png_bytep row,
04610     png_const_color_16p trans_color)
04611 {
04612    int shift, value;
04613    png_bytep sp, dp;
04614    png_uint_32 i;
04615    png_uint_32 row_width=row_info->width;
04616 
04617    png_debug(1, "in png_do_expand");
04618 
04619    {
04620       if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
04621       {
04622          png_uint_16 gray = (png_uint_16)(trans_color ? trans_color->gray : 0);
04623 
04624          if (row_info->bit_depth < 8)
04625          {
04626             switch (row_info->bit_depth)
04627             {
04628                case 1:
04629                {
04630                   gray = (png_uint_16)((gray & 0x01) * 0xff);
04631                   sp = row + (png_size_t)((row_width - 1) >> 3);
04632                   dp = row + (png_size_t)row_width - 1;
04633                   shift = 7 - (int)((row_width + 7) & 0x07);
04634                   for (i = 0; i < row_width; i++)
04635                   {
04636                      if ((*sp >> shift) & 0x01)
04637                         *dp = 0xff;
04638 
04639                      else
04640                         *dp = 0;
04641 
04642                      if (shift == 7)
04643                      {
04644                         shift = 0;
04645                         sp--;
04646                      }
04647 
04648                      else
04649                         shift++;
04650 
04651                      dp--;
04652                   }
04653                   break;
04654                }
04655 
04656                case 2:
04657                {
04658                   gray = (png_uint_16)((gray & 0x03) * 0x55);
04659                   sp = row + (png_size_t)((row_width - 1) >> 2);
04660                   dp = row + (png_size_t)row_width - 1;
04661                   shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
04662                   for (i = 0; i < row_width; i++)
04663                   {
04664                      value = (*sp >> shift) & 0x03;
04665                      *dp = (png_byte)(value | (value << 2) | (value << 4) |
04666                         (value << 6));
04667                      if (shift == 6)
04668                      {
04669                         shift = 0;
04670                         sp--;
04671                      }
04672 
04673                      else
04674                         shift += 2;
04675 
04676                      dp--;
04677                   }
04678                   break;
04679                }
04680 
04681                case 4:
04682                {
04683                   gray = (png_uint_16)((gray & 0x0f) * 0x11);
04684                   sp = row + (png_size_t)((row_width - 1) >> 1);
04685                   dp = row + (png_size_t)row_width - 1;
04686                   shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
04687                   for (i = 0; i < row_width; i++)
04688                   {
04689                      value = (*sp >> shift) & 0x0f;
04690                      *dp = (png_byte)(value | (value << 4));
04691                      if (shift == 4)
04692                      {
04693                         shift = 0;
04694                         sp--;
04695                      }
04696 
04697                      else
04698                         shift = 4;
04699 
04700                      dp--;
04701                   }
04702                   break;
04703                }
04704 
04705                default:
04706                   break;
04707             }
04708 
04709             row_info->bit_depth = 8;
04710             row_info->pixel_depth = 8;
04711             row_info->rowbytes = row_width;
04712          }
04713 
04714          if (trans_color != NULL)
04715          {
04716             if (row_info->bit_depth == 8)
04717             {
04718                gray = gray & 0xff;
04719                sp = row + (png_size_t)row_width - 1;
04720                dp = row + (png_size_t)(row_width << 1) - 1;
04721 
04722                for (i = 0; i < row_width; i++)
04723                {
04724                   if (*sp == gray)
04725                      *dp-- = 0;
04726 
04727                   else
04728                      *dp-- = 0xff;
04729 
04730                   *dp-- = *sp--;
04731                }
04732             }
04733 
04734             else if (row_info->bit_depth == 16)
04735             {
04736                png_byte gray_high = (png_byte)((gray >> 8) & 0xff);
04737                png_byte gray_low = (png_byte)(gray & 0xff);
04738                sp = row + row_info->rowbytes - 1;
04739                dp = row + (row_info->rowbytes << 1) - 1;
04740                for (i = 0; i < row_width; i++)
04741                {
04742                   if (*(sp - 1) == gray_high && *(sp) == gray_low)
04743                   {
04744                      *dp-- = 0;
04745                      *dp-- = 0;
04746                   }
04747 
04748                   else
04749                   {
04750                      *dp-- = 0xff;
04751                      *dp-- = 0xff;
04752                   }
04753 
04754                   *dp-- = *sp--;
04755                   *dp-- = *sp--;
04756                }
04757             }
04758 
04759             row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
04760             row_info->channels = 2;
04761             row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1);
04762             row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
04763                row_width);
04764          }
04765       }
04766       else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_color)
04767       {
04768          if (row_info->bit_depth == 8)
04769          {
04770             png_byte red = (png_byte)(trans_color->red & 0xff);
04771             png_byte green = (png_byte)(trans_color->green & 0xff);
04772             png_byte blue = (png_byte)(trans_color->blue & 0xff);
04773             sp = row + (png_size_t)row_info->rowbytes - 1;
04774             dp = row + (png_size_t)(row_width << 2) - 1;
04775             for (i = 0; i < row_width; i++)
04776             {
04777                if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue)
04778                   *dp-- = 0;
04779 
04780                else
04781                   *dp-- = 0xff;
04782 
04783                *dp-- = *sp--;
04784                *dp-- = *sp--;
04785                *dp-- = *sp--;
04786             }
04787          }
04788          else if (row_info->bit_depth == 16)
04789          {
04790             png_byte red_high = (png_byte)((trans_color->red >> 8) & 0xff);
04791             png_byte green_high = (png_byte)((trans_color->green >> 8) & 0xff);
04792             png_byte blue_high = (png_byte)((trans_color->blue >> 8) & 0xff);
04793             png_byte red_low = (png_byte)(trans_color->red & 0xff);
04794             png_byte green_low = (png_byte)(trans_color->green & 0xff);
04795             png_byte blue_low = (png_byte)(trans_color->blue & 0xff);
04796             sp = row + row_info->rowbytes - 1;
04797             dp = row + (png_size_t)(row_width << 3) - 1;
04798             for (i = 0; i < row_width; i++)
04799             {
04800                if (*(sp - 5) == red_high &&
04801                    *(sp - 4) == red_low &&
04802                    *(sp - 3) == green_high &&
04803                    *(sp - 2) == green_low &&
04804                    *(sp - 1) == blue_high &&
04805                    *(sp    ) == blue_low)
04806                {
04807                   *dp-- = 0;
04808                   *dp-- = 0;
04809                }
04810 
04811                else
04812                {
04813                   *dp-- = 0xff;
04814                   *dp-- = 0xff;
04815                }
04816 
04817                *dp-- = *sp--;
04818                *dp-- = *sp--;
04819                *dp-- = *sp--;
04820                *dp-- = *sp--;
04821                *dp-- = *sp--;
04822                *dp-- = *sp--;
04823             }
04824          }
04825          row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
04826          row_info->channels = 4;
04827          row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2);
04828          row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
04829       }
04830    }
04831 }
04832 #endif
04833 
04834 #ifdef PNG_READ_EXPAND_16_SUPPORTED
04835 /* If the bit depth is 8 and the color type is not a palette type expand the
04836  * whole row to 16 bits.  Has no effect otherwise.
04837  */
04838 void /* PRIVATE */
04839 png_do_expand_16(png_row_infop row_info, png_bytep row)
04840 {
04841    if (row_info->bit_depth == 8 &&
04842       row_info->color_type != PNG_COLOR_TYPE_PALETTE)
04843    {
04844       /* The row have a sequence of bytes containing [0..255] and we need
04845        * to turn it into another row containing [0..65535], to do this we
04846        * calculate:
04847        *
04848        *  (input / 255) * 65535
04849        *
04850        *  Which happens to be exactly input * 257 and this can be achieved
04851        *  simply by byte replication in place (copying backwards).
04852        */
04853       png_byte *sp = row + row_info->rowbytes; /* source, last byte + 1 */
04854       png_byte *dp = sp + row_info->rowbytes;  /* destination, end + 1 */
04855       while (dp > sp)
04856          dp[-2] = dp[-1] = *--sp, dp -= 2;
04857 
04858       row_info->rowbytes *= 2;
04859       row_info->bit_depth = 16;
04860       row_info->pixel_depth = (png_byte)(row_info->channels * 16);
04861    }
04862 }
04863 #endif
04864 
04865 #ifdef PNG_READ_QUANTIZE_SUPPORTED
04866 void /* PRIVATE */
04867 png_do_quantize(png_row_infop row_info, png_bytep row,
04868     png_const_bytep palette_lookup, png_const_bytep quantize_lookup)
04869 {
04870    png_bytep sp, dp;
04871    png_uint_32 i;
04872    png_uint_32 row_width=row_info->width;
04873 
04874    png_debug(1, "in png_do_quantize");
04875 
04876    if (row_info->bit_depth == 8)
04877    {
04878       if (row_info->color_type == PNG_COLOR_TYPE_RGB && palette_lookup)
04879       {
04880          int r, g, b, p;
04881          sp = row;
04882          dp = row;
04883          for (i = 0; i < row_width; i++)
04884          {
04885             r = *sp++;
04886             g = *sp++;
04887             b = *sp++;
04888 
04889             /* This looks real messy, but the compiler will reduce
04890              * it down to a reasonable formula.  For example, with
04891              * 5 bits per color, we get:
04892              * p = (((r >> 3) & 0x1f) << 10) |
04893              *    (((g >> 3) & 0x1f) << 5) |
04894              *    ((b >> 3) & 0x1f);
04895              */
04896             p = (((r >> (8 - PNG_QUANTIZE_RED_BITS)) &
04897                 ((1 << PNG_QUANTIZE_RED_BITS) - 1)) <<
04898                 (PNG_QUANTIZE_GREEN_BITS + PNG_QUANTIZE_BLUE_BITS)) |
04899                 (((g >> (8 - PNG_QUANTIZE_GREEN_BITS)) &
04900                 ((1 << PNG_QUANTIZE_GREEN_BITS) - 1)) <<
04901                 (PNG_QUANTIZE_BLUE_BITS)) |
04902                 ((b >> (8 - PNG_QUANTIZE_BLUE_BITS)) &
04903                 ((1 << PNG_QUANTIZE_BLUE_BITS) - 1));
04904 
04905             *dp++ = palette_lookup[p];
04906          }
04907 
04908          row_info->color_type = PNG_COLOR_TYPE_PALETTE;
04909          row_info->channels = 1;
04910          row_info->pixel_depth = row_info->bit_depth;
04911          row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
04912       }
04913 
04914       else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
04915          palette_lookup != NULL)
04916       {
04917          int r, g, b, p;
04918          sp = row;
04919          dp = row;
04920          for (i = 0; i < row_width; i++)
04921          {
04922             r = *sp++;
04923             g = *sp++;
04924             b = *sp++;
04925             sp++;
04926 
04927             p = (((r >> (8 - PNG_QUANTIZE_RED_BITS)) &
04928                 ((1 << PNG_QUANTIZE_RED_BITS) - 1)) <<
04929                 (PNG_QUANTIZE_GREEN_BITS + PNG_QUANTIZE_BLUE_BITS)) |
04930                 (((g >> (8 - PNG_QUANTIZE_GREEN_BITS)) &
04931                 ((1 << PNG_QUANTIZE_GREEN_BITS) - 1)) <<
04932                 (PNG_QUANTIZE_BLUE_BITS)) |
04933                 ((b >> (8 - PNG_QUANTIZE_BLUE_BITS)) &
04934                 ((1 << PNG_QUANTIZE_BLUE_BITS) - 1));
04935 
04936             *dp++ = palette_lookup[p];
04937          }
04938 
04939          row_info->color_type = PNG_COLOR_TYPE_PALETTE;
04940          row_info->channels = 1;
04941          row_info->pixel_depth = row_info->bit_depth;
04942          row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
04943       }
04944 
04945       else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
04946          quantize_lookup)
04947       {
04948          sp = row;
04949 
04950          for (i = 0; i < row_width; i++, sp++)
04951          {
04952             *sp = quantize_lookup[*sp];
04953          }
04954       }
04955    }
04956 }
04957 #endif /* PNG_READ_QUANTIZE_SUPPORTED */
04958 #endif /* PNG_READ_TRANSFORMS_SUPPORTED */
04959 
04960 #ifdef PNG_MNG_FEATURES_SUPPORTED
04961 /* Undoes intrapixel differencing  */
04962 void /* PRIVATE */
04963 png_do_read_intrapixel(png_row_infop row_info, png_bytep row)
04964 {
04965    png_debug(1, "in png_do_read_intrapixel");
04966 
04967    if (
04968        (row_info->color_type & PNG_COLOR_MASK_COLOR))
04969    {
04970       int bytes_per_pixel;
04971       png_uint_32 row_width = row_info->width;
04972 
04973       if (row_info->bit_depth == 8)
04974       {
04975          png_bytep rp;
04976          png_uint_32 i;
04977 
04978          if (row_info->color_type == PNG_COLOR_TYPE_RGB)
04979             bytes_per_pixel = 3;
04980 
04981          else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
04982             bytes_per_pixel = 4;
04983 
04984          else
04985             return;
04986 
04987          for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
04988          {
04989             *(rp) = (png_byte)((256 + *rp + *(rp + 1)) & 0xff);
04990             *(rp+2) = (png_byte)((256 + *(rp + 2) + *(rp + 1)) & 0xff);
04991          }
04992       }
04993       else if (row_info->bit_depth == 16)
04994       {
04995          png_bytep rp;
04996          png_uint_32 i;
04997 
04998          if (row_info->color_type == PNG_COLOR_TYPE_RGB)
04999             bytes_per_pixel = 6;
05000 
05001          else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
05002             bytes_per_pixel = 8;
05003 
05004          else
05005             return;
05006 
05007          for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
05008          {
05009             png_uint_32 s0   = (*(rp    ) << 8) | *(rp + 1);
05010             png_uint_32 s1   = (*(rp + 2) << 8) | *(rp + 3);
05011             png_uint_32 s2   = (*(rp + 4) << 8) | *(rp + 5);
05012             png_uint_32 red  = (s0 + s1 + 65536) & 0xffff;
05013             png_uint_32 blue = (s2 + s1 + 65536) & 0xffff;
05014             *(rp    ) = (png_byte)((red >> 8) & 0xff);
05015             *(rp + 1) = (png_byte)(red & 0xff);
05016             *(rp + 4) = (png_byte)((blue >> 8) & 0xff);
05017             *(rp + 5) = (png_byte)(blue & 0xff);
05018          }
05019       }
05020    }
05021 }
05022 #endif /* PNG_MNG_FEATURES_SUPPORTED */
05023 #endif /* PNG_READ_SUPPORTED */

Generated on Fri May 25 2012 04:17:39 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.