]> git.saurik.com Git - wxWidgets.git/blobdiff - src/png/pngrtran.c
Fix ribbon documentation warnings.
[wxWidgets.git] / src / png / pngrtran.c
index d10f5cff5477e2a9dd2d471fe170a889570b2a1c..e378ceba4ed684546d79cc0240c8cc3b50d59dc6 100644 (file)
@@ -1,8 +1,8 @@
 
 /* pngrtran.c - transforms the data in a row for PNG readers
  *
- * Last changed in libpng 1.5.6 [November 3, 2011]
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.2 [April 25, 2013]
+ * Copyright (c) 1998-2013 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
@@ -22,7 +22,7 @@
 
 /* Set the action on getting a CRC error for an ancillary or critical chunk. */
 void PNGAPI
-png_set_crc_action(png_structp png_ptr, int crit_action, int ancil_action)
+png_set_crc_action(png_structrp png_ptr, int crit_action, int ancil_action)
 {
    png_debug(1, "in png_set_crc_action");
 
@@ -88,16 +88,46 @@ png_set_crc_action(png_structp png_ptr, int crit_action, int ancil_action)
    }
 }
 
+#ifdef PNG_READ_TRANSFORMS_SUPPORTED
+/* Is it OK to set a transformation now?  Only if png_start_read_image or
+ * png_read_update_info have not been called.  It is not necessary for the IHDR
+ * to have been read in all cases, the parameter allows for this check too.
+ */
+static int
+png_rtran_ok(png_structrp png_ptr, int need_IHDR)
+{
+   if (png_ptr != NULL)
+   {
+      if (png_ptr->flags & PNG_FLAG_ROW_INIT)
+         png_app_error(png_ptr,
+            "invalid after png_start_read_image or png_read_update_info");
+
+      else if (need_IHDR && (png_ptr->mode & PNG_HAVE_IHDR) == 0)
+         png_app_error(png_ptr, "invalid before the PNG header has been read");
+
+      else
+      {
+         /* Turn on failure to initialize correctly for all transforms. */
+         png_ptr->flags |= PNG_FLAG_DETECT_UNINITIALIZED;
+
+         return 1; /* Ok */
+      }
+   }
+
+   return 0; /* no png_error possible! */
+}
+#endif
+
 #ifdef PNG_READ_BACKGROUND_SUPPORTED
 /* Handle alpha and tRNS via a background color */
 void PNGFAPI
-png_set_background_fixed(png_structp png_ptr,
+png_set_background_fixed(png_structrp png_ptr,
     png_const_color_16p background_color, int background_gamma_code,
     int need_expand, png_fixed_point background_gamma)
 {
    png_debug(1, "in png_set_background_fixed");
 
-   if (png_ptr == NULL)
+   if (!png_rtran_ok(png_ptr, 0) || background_color == NULL)
       return;
 
    if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN)
@@ -110,8 +140,7 @@ png_set_background_fixed(png_structp png_ptr,
    png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
    png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
 
-   png_memcpy(&(png_ptr->background), background_color,
-      png_sizeof(png_color_16));
+   png_ptr->background = *background_color;
    png_ptr->background_gamma = background_gamma;
    png_ptr->background_gamma_type = (png_byte)(background_gamma_code);
    if (need_expand)
@@ -122,7 +151,7 @@ png_set_background_fixed(png_structp png_ptr,
 
 #  ifdef PNG_FLOATING_POINT_SUPPORTED
 void PNGAPI
-png_set_background(png_structp png_ptr,
+png_set_background(png_structrp png_ptr,
     png_const_color_16p background_color, int background_gamma_code,
     int need_expand, double background_gamma)
 {
@@ -138,11 +167,11 @@ png_set_background(png_structp png_ptr,
  */
 #ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
 void PNGAPI
-png_set_scale_16(png_structp png_ptr)
+png_set_scale_16(png_structrp png_ptr)
 {
    png_debug(1, "in png_set_scale_16");
 
-   if (png_ptr == NULL)
+   if (!png_rtran_ok(png_ptr, 0))
       return;
 
    png_ptr->transformations |= PNG_SCALE_16_TO_8;
@@ -152,11 +181,11 @@ png_set_scale_16(png_structp png_ptr)
 #ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
 /* Chop 16-bit depth files to 8-bit depth */
 void PNGAPI
-png_set_strip_16(png_structp png_ptr)
+png_set_strip_16(png_structrp png_ptr)
 {
    png_debug(1, "in png_set_strip_16");
 
-   if (png_ptr == NULL)
+   if (!png_rtran_ok(png_ptr, 0))
       return;
 
    png_ptr->transformations |= PNG_16_TO_8;
@@ -165,11 +194,11 @@ png_set_strip_16(png_structp png_ptr)
 
 #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
 void PNGAPI
-png_set_strip_alpha(png_structp png_ptr)
+png_set_strip_alpha(png_structrp png_ptr)
 {
    png_debug(1, "in png_set_strip_alpha");
 
-   if (png_ptr == NULL)
+   if (!png_rtran_ok(png_ptr, 0))
       return;
 
    png_ptr->transformations |= PNG_STRIP_ALPHA;
@@ -178,7 +207,7 @@ png_set_strip_alpha(png_structp png_ptr)
 
 #if defined(PNG_READ_ALPHA_MODE_SUPPORTED) || defined(PNG_READ_GAMMA_SUPPORTED)
 static png_fixed_point
-translate_gamma_flags(png_structp png_ptr, png_fixed_point output_gamma,
+translate_gamma_flags(png_structrp png_ptr, png_fixed_point output_gamma,
    int is_screen)
 {
    /* Check for flag values.  The main reason for having the old Mac value as a
@@ -194,6 +223,8 @@ translate_gamma_flags(png_structp png_ptr, png_fixed_point output_gamma,
        */
 #     ifdef PNG_READ_sRGB_SUPPORTED
          png_ptr->flags |= PNG_FLAG_ASSUME_sRGB;
+#     else
+         PNG_UNUSED(png_ptr)
 #     endif
       if (is_screen)
          output_gamma = PNG_GAMMA_sRGB;
@@ -215,7 +246,7 @@ translate_gamma_flags(png_structp png_ptr, png_fixed_point output_gamma,
 
 #  ifdef PNG_FLOATING_POINT_SUPPORTED
 static png_fixed_point
-convert_gamma_value(png_structp png_ptr, double output_gamma)
+convert_gamma_value(png_structrp png_ptr, double output_gamma)
 {
    /* The following silently ignores cases where fixed point (times 100,000)
     * gamma values are passed to the floating point API.  This is safe and it
@@ -240,7 +271,7 @@ convert_gamma_value(png_structp png_ptr, double output_gamma)
 
 #ifdef PNG_READ_ALPHA_MODE_SUPPORTED
 void PNGFAPI
-png_set_alpha_mode_fixed(png_structp png_ptr, int mode,
+png_set_alpha_mode_fixed(png_structrp png_ptr, int mode,
    png_fixed_point output_gamma)
 {
    int compose = 0;
@@ -248,7 +279,7 @@ png_set_alpha_mode_fixed(png_structp png_ptr, int mode,
 
    png_debug(1, "in png_set_alpha_mode");
 
-   if (png_ptr == NULL)
+   if (!png_rtran_ok(png_ptr, 0))
       return;
 
    output_gamma = translate_gamma_flags(png_ptr, output_gamma, 1/*screen*/);
@@ -320,8 +351,11 @@ png_set_alpha_mode_fixed(png_structp png_ptr, int mode,
     * the side effect that the gamma in a second call to png_set_alpha_mode will
     * be ignored.)
     */
-   if (png_ptr->gamma == 0)
-      png_ptr->gamma = file_gamma;
+   if (png_ptr->colorspace.gamma == 0)
+   {
+      png_ptr->colorspace.gamma = file_gamma;
+      png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;
+   }
 
    /* But always set the output gamma: */
    png_ptr->screen_gamma = output_gamma;
@@ -332,8 +366,8 @@ png_set_alpha_mode_fixed(png_structp png_ptr, int mode,
    if (compose)
    {
       /* And obtain alpha pre-multiplication by composing on black: */
-      png_memset(&png_ptr->background, 0, sizeof png_ptr->background);
-      png_ptr->background_gamma = png_ptr->gamma; /* just in case */
+      memset(&png_ptr->background, 0, (sizeof png_ptr->background));
+      png_ptr->background_gamma = png_ptr->colorspace.gamma; /* just in case */
       png_ptr->background_gamma_type = PNG_BACKGROUND_GAMMA_FILE;
       png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND;
 
@@ -343,14 +377,11 @@ png_set_alpha_mode_fixed(png_structp png_ptr, int mode,
 
       png_ptr->transformations |= PNG_COMPOSE;
    }
-
-   /* New API, make sure apps call the correct initializers: */
-   png_ptr->flags |= PNG_FLAG_DETECT_UNINITIALIZED;
 }
 
 #  ifdef PNG_FLOATING_POINT_SUPPORTED
 void PNGAPI
-png_set_alpha_mode(png_structp png_ptr, int mode, double output_gamma)
+png_set_alpha_mode(png_structrp png_ptr, int mode, double output_gamma)
 {
    png_set_alpha_mode_fixed(png_ptr, mode, convert_gamma_value(png_ptr,
       output_gamma));
@@ -370,21 +401,21 @@ png_set_alpha_mode(png_structp png_ptr, int mode, double output_gamma)
 
 typedef struct png_dsort_struct
 {
-   struct png_dsort_struct FAR * next;
+   struct png_dsort_struct * next;
    png_byte left;
    png_byte right;
 } png_dsort;
-typedef png_dsort FAR *       png_dsortp;
-typedef png_dsort FAR * FAR * png_dsortpp;
+typedef png_dsort *   png_dsortp;
+typedef png_dsort * * png_dsortpp;
 
 void PNGAPI
-png_set_quantize(png_structp png_ptr, png_colorp palette,
+png_set_quantize(png_structrp png_ptr, png_colorp palette,
     int num_palette, int maximum_colors, png_const_uint_16p histogram,
     int full_quantize)
 {
    png_debug(1, "in png_set_quantize");
 
-   if (png_ptr == NULL)
+   if (!png_rtran_ok(png_ptr, 0))
       return;
 
    png_ptr->transformations |= PNG_QUANTIZE;
@@ -394,7 +425,7 @@ png_set_quantize(png_structp png_ptr, png_colorp palette,
       int i;
 
       png_ptr->quantize_index = (png_bytep)png_malloc(png_ptr,
-          (png_uint_32)(num_palette * png_sizeof(png_byte)));
+          (png_uint_32)(num_palette * (sizeof (png_byte))));
       for (i = 0; i < num_palette; i++)
          png_ptr->quantize_index[i] = (png_byte)i;
    }
@@ -411,7 +442,7 @@ png_set_quantize(png_structp png_ptr, png_colorp palette,
 
          /* Initialize an array to sort colors */
          png_ptr->quantize_sort = (png_bytep)png_malloc(png_ptr,
-             (png_uint_32)(num_palette * png_sizeof(png_byte)));
+             (png_uint_32)(num_palette * (sizeof (png_byte))));
 
          /* Initialize the quantize_sort array */
          for (i = 0; i < num_palette; i++)
@@ -545,9 +576,9 @@ png_set_quantize(png_structp png_ptr, png_colorp palette,
 
          /* Initialize palette index arrays */
          png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr,
-             (png_uint_32)(num_palette * png_sizeof(png_byte)));
+             (png_uint_32)(num_palette * (sizeof (png_byte))));
          png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr,
-             (png_uint_32)(num_palette * png_sizeof(png_byte)));
+             (png_uint_32)(num_palette * (sizeof (png_byte))));
 
          /* Initialize the sort array */
          for (i = 0; i < num_palette; i++)
@@ -557,7 +588,7 @@ png_set_quantize(png_structp png_ptr, png_colorp palette,
          }
 
          hash = (png_dsortpp)png_calloc(png_ptr, (png_uint_32)(769 *
-             png_sizeof(png_dsortp)));
+             (sizeof (png_dsortp))));
 
          num_new_palette = num_palette;
 
@@ -587,7 +618,7 @@ png_set_quantize(png_structp png_ptr, png_colorp palette,
                   {
 
                      t = (png_dsortp)png_malloc_warn(png_ptr,
-                         (png_uint_32)(png_sizeof(png_dsort)));
+                         (png_uint_32)(sizeof (png_dsort)));
 
                      if (t == NULL)
                          break;
@@ -712,12 +743,12 @@ png_set_quantize(png_structp png_ptr, png_colorp palette,
       png_size_t num_entries = ((png_size_t)1 << total_bits);
 
       png_ptr->palette_lookup = (png_bytep)png_calloc(png_ptr,
-          (png_uint_32)(num_entries * png_sizeof(png_byte)));
+          (png_uint_32)(num_entries * (sizeof (png_byte))));
 
       distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries *
-          png_sizeof(png_byte)));
+          (sizeof (png_byte))));
 
-      png_memset(distance, 0xff, num_entries * png_sizeof(png_byte));
+      memset(distance, 0xff, num_entries * (sizeof (png_byte)));
 
       for (i = 0; i < num_palette; i++)
       {
@@ -766,19 +797,18 @@ png_set_quantize(png_structp png_ptr, png_colorp palette,
 
 #ifdef PNG_READ_GAMMA_SUPPORTED
 void PNGFAPI
-png_set_gamma_fixed(png_structp png_ptr, png_fixed_point scrn_gamma,
+png_set_gamma_fixed(png_structrp png_ptr, png_fixed_point scrn_gamma,
    png_fixed_point file_gamma)
 {
    png_debug(1, "in png_set_gamma_fixed");
 
-   if (png_ptr == NULL)
+   if (!png_rtran_ok(png_ptr, 0))
       return;
 
    /* New in libpng-1.5.4 - reserve particular negative values as flags. */
    scrn_gamma = translate_gamma_flags(png_ptr, scrn_gamma, 1/*screen*/);
    file_gamma = translate_gamma_flags(png_ptr, file_gamma, 0/*file*/);
 
-#if PNG_LIBPNG_VER >= 10600
    /* Checking the gamma values for being >0 was added in 1.5.4 along with the
     * premultiplied alpha support; this actually hides an undocumented feature
     * of the previous implementation which allowed gamma processing to be
@@ -787,26 +817,27 @@ png_set_gamma_fixed(png_structp png_ptr, png_fixed_point scrn_gamma,
     * accept '0' for the gamma value it takes, because it isn't always used.
     *
     * Since this is an API change (albeit a very minor one that removes an
-    * undocumented API feature) it will not be made until libpng-1.6.0.
+    * undocumented API feature) the following checks were only enabled in
+    * libpng-1.6.0.
     */
    if (file_gamma <= 0)
       png_error(png_ptr, "invalid file gamma in png_set_gamma");
 
    if (scrn_gamma <= 0)
       png_error(png_ptr, "invalid screen gamma in png_set_gamma");
-#endif
 
    /* Set the gamma values unconditionally - this overrides the value in the PNG
     * file if a gAMA chunk was present.  png_set_alpha_mode provides a
     * different, easier, way to default the file gamma.
     */
-   png_ptr->gamma = file_gamma;
+   png_ptr->colorspace.gamma = file_gamma;
+   png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;
    png_ptr->screen_gamma = scrn_gamma;
 }
 
 #  ifdef PNG_FLOATING_POINT_SUPPORTED
 void PNGAPI
-png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma)
+png_set_gamma(png_structrp png_ptr, double scrn_gamma, double file_gamma)
 {
    png_set_gamma_fixed(png_ptr, convert_gamma_value(png_ptr, scrn_gamma),
       convert_gamma_value(png_ptr, file_gamma));
@@ -820,15 +851,14 @@ png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma)
  * to alpha channels.
  */
 void PNGAPI
-png_set_expand(png_structp png_ptr)
+png_set_expand(png_structrp png_ptr)
 {
    png_debug(1, "in png_set_expand");
 
-   if (png_ptr == NULL)
+   if (!png_rtran_ok(png_ptr, 0))
       return;
 
    png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
-   png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
 }
 
 /* GRR 19990627:  the following three functions currently are identical
@@ -851,40 +881,38 @@ png_set_expand(png_structp png_ptr)
 
 /* Expand paletted images to RGB. */
 void PNGAPI
-png_set_palette_to_rgb(png_structp png_ptr)
+png_set_palette_to_rgb(png_structrp png_ptr)
 {
    png_debug(1, "in png_set_palette_to_rgb");
 
-   if (png_ptr == NULL)
+   if (!png_rtran_ok(png_ptr, 0))
       return;
 
    png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
-   png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
 }
 
 /* Expand grayscale images of less than 8-bit depth to 8 bits. */
 void PNGAPI
-png_set_expand_gray_1_2_4_to_8(png_structp png_ptr)
+png_set_expand_gray_1_2_4_to_8(png_structrp png_ptr)
 {
    png_debug(1, "in png_set_expand_gray_1_2_4_to_8");
 
-   if (png_ptr == NULL)
+   if (!png_rtran_ok(png_ptr, 0))
       return;
 
    png_ptr->transformations |= PNG_EXPAND;
-   png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
 }
 
-
-
 /* Expand tRNS chunks to alpha channels. */
 void PNGAPI
-png_set_tRNS_to_alpha(png_structp png_ptr)
+png_set_tRNS_to_alpha(png_structrp png_ptr)
 {
    png_debug(1, "in png_set_tRNS_to_alpha");
 
+   if (!png_rtran_ok(png_ptr, 0))
+      return;
+
    png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
-   png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
 }
 #endif /* defined(PNG_READ_EXPAND_SUPPORTED) */
 
@@ -893,58 +921,55 @@ png_set_tRNS_to_alpha(png_structp png_ptr)
  * it may not work correctly.)
  */
 void PNGAPI
-png_set_expand_16(png_structp png_ptr)
+png_set_expand_16(png_structrp png_ptr)
 {
    png_debug(1, "in png_set_expand_16");
 
-   if (png_ptr == NULL)
+   if (!png_rtran_ok(png_ptr, 0))
       return;
 
    png_ptr->transformations |= (PNG_EXPAND_16 | PNG_EXPAND | PNG_EXPAND_tRNS);
-   png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
-
-   /* New API, make sure apps call the correct initializers: */
-   png_ptr->flags |= PNG_FLAG_DETECT_UNINITIALIZED;
 }
 #endif
 
 #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
 void PNGAPI
-png_set_gray_to_rgb(png_structp png_ptr)
+png_set_gray_to_rgb(png_structrp png_ptr)
 {
    png_debug(1, "in png_set_gray_to_rgb");
 
-   if (png_ptr != NULL)
-   {
-      /* Because rgb must be 8 bits or more: */
-      png_set_expand_gray_1_2_4_to_8(png_ptr);
-      png_ptr->transformations |= PNG_GRAY_TO_RGB;
-      png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
-   }
+   if (!png_rtran_ok(png_ptr, 0))
+      return;
+
+   /* Because rgb must be 8 bits or more: */
+   png_set_expand_gray_1_2_4_to_8(png_ptr);
+   png_ptr->transformations |= PNG_GRAY_TO_RGB;
 }
 #endif
 
 #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
 void PNGFAPI
-png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action,
+png_set_rgb_to_gray_fixed(png_structrp png_ptr, int error_action,
     png_fixed_point red, png_fixed_point green)
 {
    png_debug(1, "in png_set_rgb_to_gray");
 
-   if (png_ptr == NULL)
+   /* Need the IHDR here because of the check on color_type below. */
+   /* TODO: fix this */
+   if (!png_rtran_ok(png_ptr, 1))
       return;
 
    switch(error_action)
    {
-      case 1:
+      case PNG_ERROR_ACTION_NONE:
          png_ptr->transformations |= PNG_RGB_TO_GRAY;
          break;
 
-      case 2:
+      case PNG_ERROR_ACTION_WARN:
          png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN;
          break;
 
-      case 3:
+      case PNG_ERROR_ACTION_ERROR:
          png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR;
          break;
 
@@ -952,15 +977,19 @@ png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action,
          png_error(png_ptr, "invalid error action to rgb_to_gray");
          break;
    }
+
    if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
 #ifdef PNG_READ_EXPAND_SUPPORTED
       png_ptr->transformations |= PNG_EXPAND;
 #else
    {
-      png_warning(png_ptr,
+      /* Make this an error in 1.6 because otherwise the application may assume
+       * that it just worked and get a memory overwrite.
+       */
+      png_error(png_ptr,
         "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED");
 
-      png_ptr->transformations &= ~PNG_RGB_TO_GRAY;
+      /* png_ptr->transformations &= ~PNG_RGB_TO_GRAY; */
    }
 #endif
    {
@@ -984,7 +1013,7 @@ png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action,
       else
       {
          if (red >= 0 && green >= 0)
-            png_warning(png_ptr,
+            png_app_warning(png_ptr,
                "ignoring out of range rgb_to_gray coefficients");
 
          /* Use the defaults, from the cHRM chunk if set, else the historical
@@ -1010,31 +1039,25 @@ png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action,
  */
 
 void PNGAPI
-png_set_rgb_to_gray(png_structp png_ptr, int error_action, double red,
+png_set_rgb_to_gray(png_structrp png_ptr, int error_action, double red,
    double green)
 {
-   if (png_ptr == NULL)
-      return;
-
    png_set_rgb_to_gray_fixed(png_ptr, error_action,
       png_fixed(png_ptr, red, "rgb to gray red coefficient"),
       png_fixed(png_ptr, green, "rgb to gray green coefficient"));
 }
 #endif /* FLOATING POINT */
 
-#endif
+#endif /* RGB_TO_GRAY */
 
 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
     defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
 void PNGAPI
-png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr
+png_set_read_user_transform_fn(png_structrp png_ptr, png_user_transform_ptr
     read_user_transform_fn)
 {
    png_debug(1, "in png_set_read_user_transform_fn");
 
-   if (png_ptr == NULL)
-      return;
-
 #ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
    png_ptr->transformations |= PNG_USER_TRANSFORM;
    png_ptr->read_user_transform_fn = read_user_transform_fn;
@@ -1074,7 +1097,7 @@ png_gamma_threshold(png_fixed_point screen_gamma, png_fixed_point file_gamma)
  * extracted from 'png_init_read_transformations'.
  */
 static void /* PRIVATE */
-png_init_palette_transformations(png_structp png_ptr)
+png_init_palette_transformations(png_structrp png_ptr)
 {
    /* Called to handle the (input) palette case.  In png_do_read_transformations
     * the first step is to expand the palette if requested, so this code must
@@ -1157,7 +1180,7 @@ png_init_palette_transformations(png_structp png_ptr)
 }
 
 static void /* PRIVATE */
-png_init_rgb_transformations(png_structp png_ptr)
+png_init_rgb_transformations(png_structrp png_ptr)
 {
    /* Added to libpng-1.5.4: check the color type to determine whether there
     * is any alpha or transparency in the image and simply cancel the
@@ -1221,7 +1244,7 @@ png_init_rgb_transformations(png_structp png_ptr)
             default:
 
             case 8:
-               /* Already 8 bits, fall through */
+               /* FALL THROUGH (Already 8 bits) */
 
             case 16:
                /* Already a full 16 bits */
@@ -1242,7 +1265,7 @@ png_init_rgb_transformations(png_structp png_ptr)
 }
 
 void /* PRIVATE */
-png_init_read_transformations(png_structp png_ptr)
+png_init_read_transformations(png_structrp png_ptr)
 {
    png_debug(1, "in png_init_read_transformations");
 
@@ -1267,17 +1290,17 @@ png_init_read_transformations(png_structp png_ptr)
        */
       int gamma_correction = 0;
 
-      if (png_ptr->gamma != 0) /* has been set */
+      if (png_ptr->colorspace.gamma != 0) /* has been set */
       {
          if (png_ptr->screen_gamma != 0) /* screen set too */
-            gamma_correction = png_gamma_threshold(png_ptr->gamma,
+            gamma_correction = png_gamma_threshold(png_ptr->colorspace.gamma,
                png_ptr->screen_gamma);
 
          else
             /* Assume the output matches the input; a long time default behavior
              * of libpng, although the standard has nothing to say about this.
              */
-            png_ptr->screen_gamma = png_reciprocal(png_ptr->gamma);
+            png_ptr->screen_gamma = png_reciprocal(png_ptr->colorspace.gamma);
       }
 
       else if (png_ptr->screen_gamma != 0)
@@ -1286,7 +1309,7 @@ png_init_read_transformations(png_structp png_ptr)
           * png_set_alpha_mode (even if the alpha handling mode isn't required
           * or isn't changed from the default.)
           */
-         png_ptr->gamma = png_reciprocal(png_ptr->screen_gamma);
+         png_ptr->colorspace.gamma = png_reciprocal(png_ptr->screen_gamma);
 
       else /* neither are set */
          /* Just in case the following prevents any processing - file and screen
@@ -1294,7 +1317,10 @@ png_init_read_transformations(png_structp png_ptr)
           * third gamma value other than png_set_background with 'UNIQUE', and,
           * prior to 1.5.4
           */
-         png_ptr->screen_gamma = png_ptr->gamma = PNG_FP_1;
+         png_ptr->screen_gamma = png_ptr->colorspace.gamma = PNG_FP_1;
+
+      /* We have a gamma value now. */
+      png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;
 
       /* Now turn the gamma transformation on or off as appropriate.  Notice
        * that PNG_GAMMA just refers to the file->screen correction.  Alpha
@@ -1376,9 +1402,16 @@ png_init_read_transformations(png_structp png_ptr)
    }
 #endif
 
-#if defined(PNG_READ_EXPAND_SUPPORTED) && \
-   defined(PNG_READ_BACKGROUND_SUPPORTED) && \
-   defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
+#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
+   /* Make sure the coefficients for the rgb to gray conversion are set
+    * appropriately.
+    */
+   if (png_ptr->transformations & PNG_RGB_TO_GRAY)
+      png_colorspace_set_rgb_coefficients(png_ptr);
+#endif
+
+#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
+#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
    /* Detect gray background and attempt to enable optimization for
     * gray --> RGB case.
     *
@@ -1420,7 +1453,8 @@ png_init_read_transformations(png_structp png_ptr)
          }
       }
    }
-#endif /* PNG_READ_GRAY_TO_RGB_SUPPORTED (etc) */
+#endif /* PNG_READ_EXPAND_SUPPORTED && PNG_READ_BACKGROUND_SUPPORTED */
+#endif /* PNG_READ_GRAY_TO_RGB_SUPPORTED */
 
    /* For indexed PNG data (PNG_COLOR_TYPE_PALETTE) many of the transformations
     * can be performed directly on the palette, and some (such as rgb to gray)
@@ -1456,7 +1490,7 @@ png_init_read_transformations(png_structp png_ptr)
        * NOTE: this discards the low 16 bits of the user supplied background
        * color, but until expand_16 works properly there is no choice!
        */
-#     define CHOP(x) (x)=((png_uint_16)(((png_uint_32)(x)*255+32895) >> 16))
+#     define CHOP(x) (x)=((png_uint_16)PNG_DIV257(x))
       CHOP(png_ptr->background.red);
       CHOP(png_ptr->background.green);
       CHOP(png_ptr->background.blue);
@@ -1465,6 +1499,28 @@ png_init_read_transformations(png_structp png_ptr)
    }
 #endif /* PNG_READ_BACKGROUND_SUPPORTED && PNG_READ_EXPAND_16_SUPPORTED */
 
+#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
+   (defined(PNG_READ_SCALE_16_TO_8_SUPPORTED) || \
+   defined(PNG_READ_STRIP_16_TO_8_SUPPORTED))
+   if ((png_ptr->transformations & (PNG_16_TO_8|PNG_SCALE_16_TO_8)) &&
+      (png_ptr->transformations & PNG_COMPOSE) &&
+      !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
+      png_ptr->bit_depth == 16)
+   {
+      /* On the other hand, if a 16-bit file is to be reduced to 8-bits per
+       * component this will also happen after PNG_COMPOSE and so the background
+       * color must be pre-expanded here.
+       *
+       * TODO: fix this too.
+       */
+      png_ptr->background.red = (png_uint_16)(png_ptr->background.red * 257);
+      png_ptr->background.green =
+         (png_uint_16)(png_ptr->background.green * 257);
+      png_ptr->background.blue = (png_uint_16)(png_ptr->background.blue * 257);
+      png_ptr->background.gray = (png_uint_16)(png_ptr->background.gray * 257);
+   }
+#endif
+
    /* NOTE: below 'PNG_READ_ALPHA_MODE_SUPPORTED' is presumed to also enable the
     * background support (see the comments in scripts/pnglibconf.dfa), this
     * allows pre-multiplication of the alpha channel to be implemented as
@@ -1494,10 +1550,10 @@ png_init_read_transformations(png_structp png_ptr)
     */
    if ((png_ptr->transformations & PNG_GAMMA)
       || ((png_ptr->transformations & PNG_RGB_TO_GRAY)
-         && (png_gamma_significant(png_ptr->gamma) ||
+         && (png_gamma_significant(png_ptr->colorspace.gamma) ||
             png_gamma_significant(png_ptr->screen_gamma)))
       || ((png_ptr->transformations & PNG_COMPOSE)
-         && (png_gamma_significant(png_ptr->gamma)
+         && (png_gamma_significant(png_ptr->colorspace.gamma)
             || png_gamma_significant(png_ptr->screen_gamma)
 #  ifdef PNG_READ_BACKGROUND_SUPPORTED
             || (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_UNIQUE
@@ -1512,6 +1568,16 @@ png_init_read_transformations(png_structp png_ptr)
 #ifdef PNG_READ_BACKGROUND_SUPPORTED
       if (png_ptr->transformations & PNG_COMPOSE)
       {
+         /* Issue a warning about this combination: because RGB_TO_GRAY is
+          * optimized to do the gamma transform if present yet do_background has
+          * to do the same thing if both options are set a
+          * double-gamma-correction happens.  This is true in all versions of
+          * libpng to date.
+          */
+         if (png_ptr->transformations & PNG_RGB_TO_GRAY)
+            png_warning(png_ptr,
+               "libpng does not support gamma+background+rgb_to_gray");
+
          if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
          {
             /* We don't get to here unless there is a tRNS chunk with non-opaque
@@ -1544,8 +1610,8 @@ png_init_read_transformations(png_structp png_ptr)
                      break;
 
                   case PNG_BACKGROUND_GAMMA_FILE:
-                     g = png_reciprocal(png_ptr->gamma);
-                     gs = png_reciprocal2(png_ptr->gamma,
+                     g = png_reciprocal(png_ptr->colorspace.gamma);
+                     gs = png_reciprocal2(png_ptr->colorspace.gamma,
                         png_ptr->screen_gamma);
                      break;
 
@@ -1653,8 +1719,9 @@ png_init_read_transformations(png_structp png_ptr)
                   break;
 
                case PNG_BACKGROUND_GAMMA_FILE:
-                  g = png_reciprocal(png_ptr->gamma);
-                  gs = png_reciprocal2(png_ptr->gamma, png_ptr->screen_gamma);
+                  g = png_reciprocal(png_ptr->colorspace.gamma);
+                  gs = png_reciprocal2(png_ptr->colorspace.gamma,
+                     png_ptr->screen_gamma);
                   break;
 
                case PNG_BACKGROUND_GAMMA_UNIQUE:
@@ -1726,14 +1793,20 @@ png_init_read_transformations(png_structp png_ptr)
       else
       /* Transformation does not include PNG_BACKGROUND */
 #endif /* PNG_READ_BACKGROUND_SUPPORTED */
-      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE
+#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
+         /* RGB_TO_GRAY needs to have non-gamma-corrected values! */
+         && ((png_ptr->transformations & PNG_EXPAND) == 0 ||
+         (png_ptr->transformations & PNG_RGB_TO_GRAY) == 0)
+#endif
+         )
       {
          png_colorp palette = png_ptr->palette;
          int num_palette = png_ptr->num_palette;
          int i;
 
-         /*NOTE: there are other transformations that should probably be in here
-          * too.
+         /* NOTE: there are other transformations that should probably be in
+          * here too.
           */
          for (i = 0; i < num_palette; i++)
          {
@@ -1792,12 +1865,15 @@ png_init_read_transformations(png_structp png_ptr)
 
 #ifdef PNG_READ_SHIFT_SUPPORTED
    if ((png_ptr->transformations & PNG_SHIFT) &&
+      !(png_ptr->transformations & PNG_EXPAND) &&
        (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))
    {
       int i;
       int istop = png_ptr->num_palette;
       int shift = 8 - png_ptr->sig_bit.red;
 
+      png_ptr->transformations &= ~PNG_SHIFT;
+
       /* significant bits can be in the range 1 to 7 for a meaninful result, if
        * the number of significant bits is 0 then no shift is done (this is an
        * error condition which is silently ignored.)
@@ -1836,7 +1912,7 @@ png_init_read_transformations(png_structp png_ptr)
  * assuming the transformations result in valid PNG data.
  */
 void /* PRIVATE */
-png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
+png_read_transform_info(png_structrp png_ptr, png_inforp info_ptr)
 {
    png_debug(1, "in png_read_transform_info");
 
@@ -1887,8 +1963,12 @@ png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
     * however it seems that the code in png_init_read_transformations, which has
     * been called before this from png_read_update_info->png_read_start_row
     * sometimes does the gamma transform and cancels the flag.
+    *
+    * TODO: this looks wrong; the info_ptr should end up with a gamma equal to
+    * the screen_gamma value.  The following probably results in weirdness if
+    * the info_ptr is used by the app after the rows have been read.
     */
-   info_ptr->gamma = png_ptr->gamma;
+   info_ptr->colorspace.gamma = png_ptr->colorspace.gamma;
 #endif
 
    if (info_ptr->bit_depth == 16)
@@ -1918,7 +1998,7 @@ png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
          info_ptr->bit_depth = 8;
 #     else
 
-#        if PNG_READ_SCALE_16_TO_8_SUPPORTED
+#        ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
             png_ptr->transformations |= PNG_SCALE_16_TO_8;
             info_ptr->bit_depth = 8;
 #        else
@@ -2036,7 +2116,7 @@ defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
  * decide how it fits in with the other transformations here.
  */
 void /* PRIVATE */
-png_do_read_transformations(png_structp png_ptr, png_row_infop row_info)
+png_do_read_transformations(png_structrp png_ptr, png_row_infop row_info)
 {
    png_debug(1, "in png_do_read_transformations");
 
@@ -2051,8 +2131,9 @@ png_do_read_transformations(png_structp png_ptr, png_row_infop row_info)
 
    /* The following is debugging; prior to 1.5.4 the code was never compiled in;
     * in 1.5.4 PNG_FLAG_DETECT_UNINITIALIZED was added and the macro
-    * PNG_WARN_UNINITIALIZED_ROW removed.  In 1.5 the new flag is set only for
-    * selected new APIs to ensure that there is no API change.
+    * PNG_WARN_UNINITIALIZED_ROW removed.  In 1.6 the new flag is set only for
+    * all transformations, however in practice the ROW_INIT always gets done on
+    * demand, if necessary.
     */
    if ((png_ptr->flags & PNG_FLAG_DETECT_UNINITIALIZED) != 0 &&
       !(png_ptr->flags & PNG_FLAG_ROW_INIT))
@@ -2157,20 +2238,30 @@ png_do_read_transformations(png_structp png_ptr, png_row_infop row_info)
       png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1);
 #endif
 
-#if (defined PNG_READ_BACKGROUND_SUPPORTED) ||\
-   (defined PNG_READ_ALPHA_MODE_SUPPORTED)
+#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
+   defined(PNG_READ_ALPHA_MODE_SUPPORTED)
    if (png_ptr->transformations & PNG_COMPOSE)
       png_do_compose(row_info, png_ptr->row_buf + 1, png_ptr);
 #endif
 
 #ifdef PNG_READ_GAMMA_SUPPORTED
    if ((png_ptr->transformations & PNG_GAMMA) &&
-#if (defined PNG_READ_BACKGROUND_SUPPORTED) ||\
-   (defined PNG_READ_ALPHA_MODE_SUPPORTED)
+#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
+      /* Because RGB_TO_GRAY does the gamma transform. */
+      !(png_ptr->transformations & PNG_RGB_TO_GRAY) &&
+#endif
+#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
+   defined(PNG_READ_ALPHA_MODE_SUPPORTED)
+      /* Because PNG_COMPOSE does the gamma transform if there is something to
+       * do (if there is an alpha channel or transparency.)
+       */
        !((png_ptr->transformations & PNG_COMPOSE) &&
        ((png_ptr->num_trans != 0) ||
        (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) &&
 #endif
+      /* Because png_init_read_transformations transforms the palette, unless
+       * RGB_TO_GRAY will do the transform.
+       */
        (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE))
       png_do_gamma(row_info, png_ptr->row_buf + 1, png_ptr);
 #endif
@@ -2226,7 +2317,7 @@ png_do_read_transformations(png_structp png_ptr, png_row_infop row_info)
 #endif
 
 #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
-   /*NOTE: moved here in 1.5.4 (from much later in this list.) */
+   /* NOTE: moved here in 1.5.4 (from much later in this list.) */
    if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
        (png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
       png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1);
@@ -2248,6 +2339,13 @@ png_do_read_transformations(png_structp png_ptr, png_row_infop row_info)
       png_do_unpack(row_info, png_ptr->row_buf + 1);
 #endif
 
+#ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED
+   /* Added at libpng-1.5.10 */
+   if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
+       png_ptr->num_palette_max >= 0)
+      png_do_check_palette_indexes(png_ptr, row_info);
+#endif
+
 #ifdef PNG_READ_BGR_SUPPORTED
    if (png_ptr->transformations & PNG_BGR)
       png_do_bgr(row_info, png_ptr->row_buf + 1);
@@ -2562,7 +2660,7 @@ png_do_scale_16_to_8(png_row_infop row_info, png_bytep row)
    if (row_info->bit_depth == 16)
    {
       png_bytep sp = row; /* source */
-      png_bytep dp = row; /* destinaton */
+      png_bytep dp = row; /* destination */
       png_bytep ep = sp + row_info->rowbytes; /* end+1 */
 
       while (sp < ep)
@@ -2623,7 +2721,7 @@ png_do_chop(png_row_infop row_info, png_bytep row)
    if (row_info->bit_depth == 16)
    {
       png_bytep sp = row; /* source */
-      png_bytep dp = row; /* destinaton */
+      png_bytep dp = row; /* destination */
       png_bytep ep = sp + row_info->rowbytes; /* end+1 */
 
       while (sp < ep)
@@ -3166,7 +3264,7 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
  *  to that used above.
  */
 int /* PRIVATE */
-png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
+png_do_rgb_to_gray(png_structrp png_ptr, png_row_infop row_info, png_bytep row)
 
 {
    int rgb_error = 0;
@@ -3185,7 +3283,7 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
 
       if (row_info->bit_depth == 8)
       {
-#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
+#ifdef PNG_READ_GAMMA_SUPPORTED
          /* Notice that gamma to/from 1 are not necessarily inverses (if
           * there is an overall gamma correction).  Prior to 1.5.5 this code
           * checked the linearized values for equality; this doesn't match
@@ -3245,7 +3343,7 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
                if (red != green || red != blue)
                {
                   rgb_error |= 1;
-                  /*NOTE: this is the historical approach which simply
+                  /* NOTE: this is the historical approach which simply
                    * truncates the results.
                    */
                   *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15);
@@ -3262,7 +3360,7 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
 
       else /* RGB bit_depth == 16 */
       {
-#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
+#ifdef PNG_READ_GAMMA_SUPPORTED
          if (png_ptr->gamma_16_to_1 != NULL && png_ptr->gamma_16_from_1 != NULL)
          {
             png_bytep sp = row;
@@ -3331,7 +3429,7 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
                if (red != green || red != blue)
                   rgb_error |= 1;
 
-               /* From 1.5.5 in the 16 bit case do the accurate convertion even
+               /* From 1.5.5 in the 16 bit case do the accurate conversion even
                 * in the 'fast' case - this is because this is where the code
                 * ends up when handling linear 16 bit data.
                 */
@@ -3419,14 +3517,14 @@ png_build_grayscale_palette(int bit_depth, png_colorp palette)
 
 
 #ifdef PNG_READ_TRANSFORMS_SUPPORTED
-#if (defined PNG_READ_BACKGROUND_SUPPORTED) ||\
-   (defined PNG_READ_ALPHA_MODE_SUPPORTED)
+#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
+   defined(PNG_READ_ALPHA_MODE_SUPPORTED)
 /* Replace any alpha or transparency with the supplied background color.
  * "background" is already in the screen gamma, while "background_1" is
  * at a gamma of 1.0.  Paletted files have already been taken care of.
  */
 void /* PRIVATE */
-png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
+png_do_compose(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
 {
 #ifdef PNG_READ_GAMMA_SUPPORTED
    png_const_bytep gamma_table = png_ptr->gamma_table;
@@ -3436,12 +3534,12 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
    png_const_uint_16pp gamma_16_from_1 = png_ptr->gamma_16_from_1;
    png_const_uint_16pp gamma_16_to_1 = png_ptr->gamma_16_to_1;
    int gamma_shift = png_ptr->gamma_shift;
+   int optimize = (png_ptr->flags & PNG_FLAG_OPTIMIZE_ALPHA) != 0;
 #endif
 
    png_bytep sp;
    png_uint_32 i;
    png_uint_32 row_width = row_info->width;
-   int optimize = (png_ptr->flags & PNG_FLAG_OPTIMIZE_ALPHA) != 0;
    int shift;
 
    png_debug(1, "in png_do_compose");
@@ -3462,8 +3560,9 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
                      if ((png_uint_16)((*sp >> shift) & 0x01)
                         == png_ptr->trans_color.gray)
                      {
-                        *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
-                        *sp |= (png_byte)(png_ptr->background.gray << shift);
+                        unsigned int tmp = *sp & (0x7f7f >> (7 - shift));
+                        tmp |= png_ptr->background.gray << shift;
+                        *sp = (png_byte)(tmp & 0xff);
                      }
 
                      if (!shift)
@@ -3490,17 +3589,19 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
                         if ((png_uint_16)((*sp >> shift) & 0x03)
                             == png_ptr->trans_color.gray)
                         {
-                           *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
-                           *sp |= (png_byte)(png_ptr->background.gray << shift);
+                           unsigned int tmp = *sp & (0x3f3f >> (6 - shift));
+                           tmp |= png_ptr->background.gray << shift;
+                           *sp = (png_byte)(tmp & 0xff);
                         }
 
                         else
                         {
-                           png_byte p = (png_byte)((*sp >> shift) & 0x03);
-                           png_byte g = (png_byte)((gamma_table [p | (p << 2) |
-                               (p << 4) | (p << 6)] >> 6) & 0x03);
-                           *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
-                           *sp |= (png_byte)(g << shift);
+                           unsigned int p = (*sp >> shift) & 0x03;
+                           unsigned int g = (gamma_table [p | (p << 2) |
+                               (p << 4) | (p << 6)] >> 6) & 0x03;
+                           unsigned int tmp = *sp & (0x3f3f >> (6 - shift));
+                           tmp |= g << shift;
+                           *sp = (png_byte)(tmp & 0xff);
                         }
 
                         if (!shift)
@@ -3524,8 +3625,9 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
                         if ((png_uint_16)((*sp >> shift) & 0x03)
                             == png_ptr->trans_color.gray)
                         {
-                           *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
-                           *sp |= (png_byte)(png_ptr->background.gray << shift);
+                           unsigned int tmp = *sp & (0x3f3f >> (6 - shift));
+                           tmp |= png_ptr->background.gray << shift;
+                           *sp = (png_byte)(tmp & 0xff);
                         }
 
                         if (!shift)
@@ -3553,17 +3655,19 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
                         if ((png_uint_16)((*sp >> shift) & 0x0f)
                             == png_ptr->trans_color.gray)
                         {
-                           *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
-                           *sp |= (png_byte)(png_ptr->background.gray << shift);
+                           unsigned int tmp = *sp & (0xf0f >> (4 - shift));
+                           tmp |= png_ptr->background.gray << shift;
+                           *sp = (png_byte)(tmp & 0xff);
                         }
 
                         else
                         {
-                           png_byte p = (png_byte)((*sp >> shift) & 0x0f);
-                           png_byte g = (png_byte)((gamma_table[p |
-                               (p << 4)] >> 4) & 0x0f);
-                           *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
-                           *sp |= (png_byte)(g << shift);
+                           unsigned int p = (*sp >> shift) & 0x0f;
+                           unsigned int g = (gamma_table[p | (p << 4)] >> 4) &
+                              0x0f;
+                           unsigned int tmp = *sp & (0xf0f >> (4 - shift));
+                           tmp |= g << shift;
+                           *sp = (png_byte)(tmp & 0xff);
                         }
 
                         if (!shift)
@@ -3587,8 +3691,9 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
                         if ((png_uint_16)((*sp >> shift) & 0x0f)
                             == png_ptr->trans_color.gray)
                         {
-                           *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
-                           *sp |= (png_byte)(png_ptr->background.gray << shift);
+                           unsigned int tmp = *sp & (0xf0f >> (4 - shift));
+                           tmp |= png_ptr->background.gray << shift;
+                           *sp = (png_byte)(tmp & 0xff);
                         }
 
                         if (!shift)
@@ -3647,8 +3752,10 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
                         if (v == png_ptr->trans_color.gray)
                         {
                            /* Background is already in screen gamma */
-                           *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
-                           *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
+                           *sp = (png_byte)((png_ptr->background.gray >> 8)
+                                & 0xff);
+                           *(sp + 1) = (png_byte)(png_ptr->background.gray
+                                & 0xff);
                         }
 
                         else
@@ -3671,8 +3778,10 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
 
                         if (v == png_ptr->trans_color.gray)
                         {
-                           *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
-                           *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
+                           *sp = (png_byte)((png_ptr->background.gray >> 8)
+                                & 0xff);
+                           *(sp + 1) = (png_byte)(png_ptr->background.gray
+                                & 0xff);
                         }
                      }
                   }
@@ -3752,9 +3861,12 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
                         /* Background is already in screen gamma */
                         *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
                         *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
-                        *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff);
-                        *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff);
-                        *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff);
+                        *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
+                                & 0xff);
+                        *(sp + 3) = (png_byte)(png_ptr->background.green
+                                & 0xff);
+                        *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
+                                & 0xff);
                         *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
                      }
 
@@ -3795,9 +3907,12 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
                      {
                         *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
                         *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
-                        *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff);
-                        *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff);
-                        *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff);
+                        *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
+                                & 0xff);
+                        *(sp + 3) = (png_byte)(png_ptr->background.green
+                                & 0xff);
+                        *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
+                                & 0xff);
                         *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
                      }
                   }
@@ -3852,7 +3967,7 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
                         *sp = (png_byte)png_ptr->background.gray;
 
                      else if (a < 0xff)
-                        png_composite(*sp, *sp, a, png_ptr->background_1.gray);
+                        png_composite(*sp, *sp, a, png_ptr->background.gray);
                   }
                }
             }
@@ -3880,7 +3995,8 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
                      else if (a == 0)
                      {
                         /* Background is already in screen gamma */
-                        *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
+                        *sp = (png_byte)((png_ptr->background.gray >> 8)
+                                & 0xff);
                         *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
                      }
 
@@ -3910,7 +4026,8 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
 
                      if (a == 0)
                      {
-                        *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
+                        *sp = (png_byte)((png_ptr->background.gray >> 8)
+                                & 0xff);
                         *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
                      }
 
@@ -3919,7 +4036,7 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
                         png_uint_16 g, v;
 
                         g = (png_uint_16)(((*sp) << 8) + *(sp + 1));
-                        png_composite_16(v, g, a, png_ptr->background_1.gray);
+                        png_composite_16(v, g, a, png_ptr->background.gray);
                         *sp = (png_byte)((v >> 8) & 0xff);
                         *(sp + 1) = (png_byte)(v & 0xff);
                      }
@@ -4040,9 +4157,12 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
                         /* Background is already in screen gamma */
                         *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
                         *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
-                        *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff);
-                        *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff);
-                        *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff);
+                        *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
+                                & 0xff);
+                        *(sp + 3) = (png_byte)(png_ptr->background.green
+                                & 0xff);
+                        *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
+                                & 0xff);
                         *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
                      }
 
@@ -4053,14 +4173,16 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
                         v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
                         png_composite_16(w, v, a, png_ptr->background_1.red);
                         if (!optimize)
-                           w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
+                           w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >>
+                                8];
                         *sp = (png_byte)((w >> 8) & 0xff);
                         *(sp + 1) = (png_byte)(w & 0xff);
 
                         v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)];
                         png_composite_16(w, v, a, png_ptr->background_1.green);
                         if (!optimize)
-                           w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
+                           w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >>
+                                8];
 
                         *(sp + 2) = (png_byte)((w >> 8) & 0xff);
                         *(sp + 3) = (png_byte)(w & 0xff);
@@ -4068,7 +4190,8 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
                         v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)];
                         png_composite_16(w, v, a, png_ptr->background_1.blue);
                         if (!optimize)
-                           w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
+                           w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >>
+                                8];
 
                         *(sp + 4) = (png_byte)((w >> 8) & 0xff);
                         *(sp + 5) = (png_byte)(w & 0xff);
@@ -4089,9 +4212,12 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
                      {
                         *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
                         *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
-                        *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff);
-                        *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff);
-                        *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff);
+                        *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
+                                & 0xff);
+                        *(sp + 3) = (png_byte)(png_ptr->background.green
+                                & 0xff);
+                        *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
+                                & 0xff);
                         *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
                      }
 
@@ -4138,7 +4264,7 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
  * build_gamma_table().
  */
 void /* PRIVATE */
-png_do_gamma(png_row_infop row_info, png_bytep row, png_structp png_ptr)
+png_do_gamma(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
 {
    png_const_bytep gamma_table = png_ptr->gamma_table;
    png_const_uint_16pp gamma_16_table = png_ptr->gamma_16_table;
@@ -4339,7 +4465,7 @@ png_do_gamma(png_row_infop row_info, png_bytep row, png_structp png_ptr)
  * from_1 tables.
  */
 void /* PRIVATE */
-png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structp png_ptr)
+png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
 {
    png_uint_32 row_width = row_info->width;
 
@@ -4571,7 +4697,7 @@ png_do_expand(png_row_infop row_info, png_bytep row,
    {
       if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
       {
-         png_uint_16 gray = (png_uint_16)(trans_color ? trans_color->gray : 0);
+         unsigned int gray = trans_color ? trans_color->gray : 0;
 
          if (row_info->bit_depth < 8)
          {
@@ -4579,7 +4705,7 @@ png_do_expand(png_row_infop row_info, png_bytep row,
             {
                case 1:
                {
-                  gray = (png_uint_16)((gray & 0x01) * 0xff);
+                  gray = (gray & 0x01) * 0xff;
                   sp = row + (png_size_t)((row_width - 1) >> 3);
                   dp = row + (png_size_t)row_width - 1;
                   shift = 7 - (int)((row_width + 7) & 0x07);
@@ -4607,7 +4733,7 @@ png_do_expand(png_row_infop row_info, png_bytep row,
 
                case 2:
                {
-                  gray = (png_uint_16)((gray & 0x03) * 0x55);
+                  gray = (gray & 0x03) * 0x55;
                   sp = row + (png_size_t)((row_width - 1) >> 2);
                   dp = row + (png_size_t)row_width - 1;
                   shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
@@ -4632,7 +4758,7 @@ png_do_expand(png_row_infop row_info, png_bytep row,
 
                case 4:
                {
-                  gray = (png_uint_16)((gray & 0x0f) * 0x11);
+                  gray = (gray & 0x0f) * 0x11;
                   sp = row + (png_size_t)((row_width - 1) >> 1);
                   dp = row + (png_size_t)row_width - 1;
                   shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
@@ -4685,8 +4811,8 @@ png_do_expand(png_row_infop row_info, png_bytep row,
 
             else if (row_info->bit_depth == 16)
             {
-               png_byte gray_high = (png_byte)((gray >> 8) & 0xff);
-               png_byte gray_low = (png_byte)(gray & 0xff);
+               unsigned int gray_high = (gray >> 8) & 0xff;
+               unsigned int gray_low = gray & 0xff;
                sp = row + row_info->rowbytes - 1;
                dp = row + (row_info->rowbytes << 1) - 1;
                for (i = 0; i < row_width; i++)