]> rtime.felk.cvut.cz Git - l4.git/blobdiff - l4/pkg/libpng/lib/dist/pngrtran.c
update
[l4.git] / l4 / pkg / libpng / lib / dist / pngrtran.c
index 064d92b7e44967f9acc720338e3b5192a6e44f9c..a485cacc4f76dffc73c0b5a17e776c2a7a717901 100644 (file)
@@ -1,7 +1,7 @@
 
 /* pngrtran.c - transforms the data in a row for PNG readers
  *
- * Last changed in libpng 1.5.14 [January 24, 2013]
+ * Last changed in libpng 1.6.0 [February 14, 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
@@ -215,7 +244,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 +269,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 +277,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 +349,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 +364,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 +375,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 +399,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 +423,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 +440,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 +574,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 +586,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 +616,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 +741,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 +795,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 +815,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 +849,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 +879,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,45 +919,42 @@ 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)
@@ -952,15 +975,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 +1011,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,29 +1037,26 @@ 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)
+   if (!png_rtran_ok(png_ptr, 0))
       return;
 
 #ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
@@ -1074,7 +1098,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 +1181,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 +1245,7 @@ png_init_rgb_transformations(png_structp png_ptr)
             default:
 
             case 8:
-               /* FALL THROUGH (already 8 bits) */
+               /* FALL THROUGH (Already 8 bits) */
 
             case 16:
                /* Already a full 16 bits */
@@ -1242,7 +1266,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 +1291,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 +1310,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 +1318,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 +1403,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 +1454,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 +1491,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);
@@ -1516,10 +1551,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
@@ -1576,8 +1611,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;
 
@@ -1685,8 +1720,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:
@@ -1877,7 +1913,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");
 
@@ -1928,8 +1964,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)
@@ -2077,7 +2117,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");
 
@@ -2092,8 +2132,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))
@@ -3224,7 +3265,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;
@@ -3243,7 +3284,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
@@ -3320,7 +3361,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;
@@ -3484,7 +3525,7 @@ png_build_grayscale_palette(int bit_depth, png_colorp palette)
  * 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;
@@ -3494,12 +3535,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");
@@ -3520,8 +3561,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)
@@ -3548,17 +3590,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)
@@ -3582,8 +3626,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)
@@ -3611,17 +3656,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)
@@ -3645,8 +3692,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)
@@ -4126,16 +4174,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);
@@ -4143,8 +4191,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);
@@ -4217,7 +4265,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;
@@ -4418,7 +4466,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;
 
@@ -4650,7 +4698,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)
          {
@@ -4658,7 +4706,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);
@@ -4686,7 +4734,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);
@@ -4711,7 +4759,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);
@@ -4746,9 +4794,7 @@ png_do_expand(png_row_infop row_info, png_bytep row,
          {
             if (row_info->bit_depth == 8)
             {
-               /* NOTE: prior to libpng 1.5.14 this cleared out the top bits of
-                * 'gray', however if those are set it is an error.
-                */
+               gray = gray & 0xff;
                sp = row + (png_size_t)row_width - 1;
                dp = row + (png_size_t)(row_width << 1) - 1;
 
@@ -4766,8 +4812,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++)