[devel] Cleanup of conditional compilation code and of background/gamma

handling. Internal changes only except for a new option to avoid compiling
in the png_build_grayscale_palette API (which is not used at all internally.)
The main change is to move the transform tests (READ_TRANSFORMS,
WRITE_TRANSFORMS) up one level to the caller of the APIs.
diff --git a/png.h b/png.h
index 6440485..7f162ba 100644
--- a/png.h
+++ b/png.h
@@ -1100,8 +1100,10 @@
     png_ptr));
 #endif
 
+#ifdef PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED
 PNG_EXPORT(35, void, png_build_grayscale_palette, (int bit_depth,
     png_colorp palette));
+#endif
 
 #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
 PNG_EXPORT(36, void, png_set_strip_alpha, (png_structp png_ptr));
diff --git a/pngpread.c b/pngpread.c
index d042eff..a50292a 100644
--- a/pngpread.c
+++ b/pngpread.c
@@ -1026,8 +1026,10 @@
 
    png_memcpy(png_ptr->prev_row, png_ptr->row_buf, png_ptr->rowbytes + 1);
 
+#ifdef PNG_READ_TRANSFORMS_SUPPORTED
    if (png_ptr->transformations)
       png_do_read_transformations(png_ptr);
+#endif
 
 #ifdef PNG_READ_INTERLACING_SUPPORTED
    /* Blow up interlaced rows to full size */
diff --git a/pngpriv.h b/pngpriv.h
index 82fbac8..3486c13 100644
--- a/pngpriv.h
+++ b/pngpriv.h
@@ -743,9 +743,12 @@
 
 /* Initialize the row buffers, etc. */
 PNG_EXTERN void png_read_start_row PNGARG((png_structp png_ptr));
+
+#ifdef PNG_READ_TRANSFORMS_SUPPORTED
 /* Optional call to update the users info structure */
 PNG_EXTERN void png_read_transform_info PNGARG((png_structp png_ptr,
     png_infop info_ptr));
+#endif
 
 /* These are the functions that do the transformations */
 #ifdef PNG_READ_FILLER_SUPPORTED
@@ -849,25 +852,13 @@
 #endif
 
 #ifdef PNG_READ_BACKGROUND_SUPPORTED
-#  ifdef PNG_READ_GAMMA_SUPPORTED
 PNG_EXTERN void png_do_background PNGARG((png_row_infop row_info,
-    png_bytep row, png_const_color_16p trans_color,
-    png_const_color_16p background, png_const_color_16p background_1,
-    png_const_bytep gamma_table, png_const_bytep gamma_from_1,
-    png_const_bytep gamma_to_1, png_const_uint_16pp gamma_16,
-    png_const_uint_16pp gamma_16_from_1, png_const_uint_16pp gamma_16_to_1,
-    int gamma_shift));
-#  else
-PNG_EXTERN void png_do_background PNGARG((png_row_infop row_info,
-    png_bytep row, png_const_color_16p trans_color,
-    png_const_color_16p background));
-#  endif
+    png_bytep row, png_structp png_ptr));
 #endif
 
 #ifdef PNG_READ_GAMMA_SUPPORTED
 PNG_EXTERN void png_do_gamma PNGARG((png_row_infop row_info,
-    png_bytep row, png_const_bytep gamma_table,
-    png_const_uint_16pp gamma_16_table, int gamma_shift));
+    png_bytep row, png_structp png_ptr));
 #endif
 
 #ifdef PNG_READ_EXPAND_SUPPORTED
@@ -987,10 +978,16 @@
     png_const_bytep chunk_name));
 
 /* Handle the transformations for reading and writing */
+#ifdef PNG_READ_TRANSFORMS_SUPPORTED
 PNG_EXTERN void png_do_read_transformations PNGARG((png_structp png_ptr));
+#endif
+#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED
 PNG_EXTERN void png_do_write_transformations PNGARG((png_structp png_ptr));
+#endif
 
+#ifdef PNG_READ_TRANSFORMS_SUPPORTED
 PNG_EXTERN void png_init_read_transformations PNGARG((png_structp png_ptr));
+#endif
 
 #ifdef PNG_PROGRESSIVE_READ_SUPPORTED
 PNG_EXTERN void png_push_read_chunk PNGARG((png_structp png_ptr,
diff --git a/pngread.c b/pngread.c
index aa84001..07eb762 100644
--- a/pngread.c
+++ b/pngread.c
@@ -457,7 +457,11 @@
           "Ignoring extra png_read_update_info() call;"
           " row buffer not reallocated");
 
+#ifdef PNG_READ_TRANSFORMS_SUPPORTED
    png_read_transform_info(png_ptr, info_ptr);
+#else
+   PNG_UNUSED(info_ptr)
+#endif
 }
 
 #ifdef PNG_SEQUENTIAL_READ_SUPPORTED
@@ -704,8 +708,10 @@
 #endif
 
 
+#ifdef PNG_READ_TRANSFORMS_SUPPORTED
    if (png_ptr->transformations)
       png_do_read_transformations(png_ptr);
+#endif
 
 #ifdef PNG_READ_INTERLACING_SUPPORTED
    /* Blow up interlaced rows to full size */
diff --git a/pngrtran.c b/pngrtran.c
index ab78290..76892ae 100644
--- a/pngrtran.c
+++ b/pngrtran.c
@@ -137,7 +137,6 @@
       return;
 
    png_ptr->transformations |= PNG_16_TO_8;
-   png_ptr->transformations &= ~PNG_EXPAND_16;
 }
 #endif
 
@@ -700,8 +699,6 @@
       return;
 
    png_ptr->transformations |= (PNG_EXPAND_16 | PNG_EXPAND | PNG_EXPAND_tRNS);
-   png_ptr->transformations &= ~PNG_16_TO_8;
-
    png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
 }
 #endif
@@ -827,6 +824,7 @@
 }
 #endif
 
+#ifdef PNG_READ_TRANSFORMS_SUPPORTED
 /* Initialize everything needed for the read.  This includes modifying
  * the palette.
  */
@@ -1559,16 +1557,7 @@
    if ((png_ptr->transformations & PNG_BACKGROUND) &&
        ((png_ptr->num_trans != 0) ||
        (png_ptr->color_type & PNG_COLOR_MASK_ALPHA)))
-      png_do_background(&(png_ptr->row_info), png_ptr->row_buf + 1,
-          &(png_ptr->trans_color), &(png_ptr->background)
-#ifdef PNG_READ_GAMMA_SUPPORTED
-          , &(png_ptr->background_1),
-          png_ptr->gamma_table, png_ptr->gamma_from_1,
-          png_ptr->gamma_to_1, png_ptr->gamma_16_table,
-          png_ptr->gamma_16_from_1, png_ptr->gamma_16_to_1,
-          png_ptr->gamma_shift
-#endif
-          );
+      png_do_background(&(png_ptr->row_info), png_ptr->row_buf + 1, png_ptr);
 #endif
 
 #ifdef PNG_READ_GAMMA_SUPPORTED
@@ -1579,9 +1568,7 @@
        (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) &&
 #endif
        (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE))
-      png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1,
-          png_ptr->gamma_table, png_ptr->gamma_16_table,
-          png_ptr->gamma_shift);
+      png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1, png_ptr);
 #endif
 
 #ifdef PNG_READ_16_TO_8_SUPPORTED
@@ -2721,11 +2708,13 @@
    return rgb_error;
 }
 #endif
+#endif /* PNG_READ_TRANSFORMS_SUPPORTED */
 
+#ifdef PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED
 /* Build a grayscale palette.  Palette is assumed to be 1 << bit_depth
  * large of png_color.  This lets grayscale images be treated as
  * paletted.  Most useful for gamma correction and simplification
- * of code.
+ * of code.  This API is not used internally.
  */
 void PNGAPI
 png_build_grayscale_palette(int bit_depth, png_colorp palette)
@@ -2775,24 +2764,28 @@
       palette[i].blue = (png_byte)v;
    }
 }
+#endif
 
 
+#ifdef PNG_READ_TRANSFORMS_SUPPORTED
 #ifdef PNG_READ_BACKGROUND_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_background(png_row_infop row_info, png_bytep row,
-    png_const_color_16p trans_color, png_const_color_16p background
-#ifdef PNG_READ_GAMMA_SUPPORTED
-    , png_const_color_16p background_1, png_const_bytep gamma_table,
-    png_const_bytep gamma_from_1, png_const_bytep gamma_to_1,
-    png_const_uint_16pp gamma_16, png_const_uint_16pp gamma_16_from_1,
-    png_const_uint_16pp gamma_16_to_1, int gamma_shift
-#endif
-    )
+png_do_background(png_row_infop row_info, png_bytep row, png_structp png_ptr)
 {
+#ifdef PNG_READ_GAMMA_SUPPORTED
+   png_const_bytep gamma_table = png_ptr->gamma_table;
+   png_const_bytep gamma_from_1 = png_ptr->gamma_from_1;
+   png_const_bytep gamma_to_1 = png_ptr->gamma_to_1;
+   png_const_uint_16pp gamma_16 = png_ptr->gamma_16_table;
+   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;
+#endif
+
    png_bytep sp, dp;
    png_uint_32 i;
    png_uint_32 row_width = row_info->width;
@@ -2800,9 +2793,8 @@
 
    png_debug(1, "in png_do_background");
 
-   if (background != NULL &&
-      (!(row_info->color_type & PNG_COLOR_MASK_ALPHA) ||
-      (row_info->color_type != PNG_COLOR_TYPE_PALETTE && trans_color)))
+   if (!(row_info->color_type & PNG_COLOR_MASK_ALPHA) ||
+      row_info->color_type != PNG_COLOR_TYPE_PALETTE)
    {
       switch (row_info->color_type)
       {
@@ -2817,10 +2809,10 @@
                   for (i = 0; i < row_width; i++)
                   {
                      if ((png_uint_16)((*sp >> shift) & 0x01)
-                        == trans_color->gray)
+                        == png_ptr->trans_color.gray)
                      {
                         *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
-                        *sp |= (png_byte)(background->gray << shift);
+                        *sp |= (png_byte)(png_ptr->background.gray << shift);
                      }
 
                      if (!shift)
@@ -2845,10 +2837,10 @@
                      for (i = 0; i < row_width; i++)
                      {
                         if ((png_uint_16)((*sp >> shift) & 0x03)
-                            == trans_color->gray)
+                            == png_ptr->trans_color.gray)
                         {
                            *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
-                           *sp |= (png_byte)(background->gray << shift);
+                           *sp |= (png_byte)(png_ptr->background.gray << shift);
                         }
 
                         else
@@ -2879,10 +2871,10 @@
                      for (i = 0; i < row_width; i++)
                      {
                         if ((png_uint_16)((*sp >> shift) & 0x03)
-                            == trans_color->gray)
+                            == png_ptr->trans_color.gray)
                         {
                            *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
-                           *sp |= (png_byte)(background->gray << shift);
+                           *sp |= (png_byte)(png_ptr->background.gray << shift);
                         }
 
                         if (!shift)
@@ -2908,10 +2900,10 @@
                      for (i = 0; i < row_width; i++)
                      {
                         if ((png_uint_16)((*sp >> shift) & 0x0f)
-                            == trans_color->gray)
+                            == png_ptr->trans_color.gray)
                         {
                            *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
-                           *sp |= (png_byte)(background->gray << shift);
+                           *sp |= (png_byte)(png_ptr->background.gray << shift);
                         }
 
                         else
@@ -2942,10 +2934,10 @@
                      for (i = 0; i < row_width; i++)
                      {
                         if ((png_uint_16)((*sp >> shift) & 0x0f)
-                            == trans_color->gray)
+                            == png_ptr->trans_color.gray)
                         {
                            *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
-                           *sp |= (png_byte)(background->gray << shift);
+                           *sp |= (png_byte)(png_ptr->background.gray << shift);
                         }
 
                         if (!shift)
@@ -2969,8 +2961,8 @@
                      sp = row;
                      for (i = 0; i < row_width; i++, sp++)
                      {
-                        if (*sp == trans_color->gray)
-                           *sp = (png_byte)background->gray;
+                        if (*sp == png_ptr->trans_color.gray)
+                           *sp = (png_byte)png_ptr->background.gray;
 
                         else
                            *sp = gamma_table[*sp];
@@ -2982,8 +2974,8 @@
                      sp = row;
                      for (i = 0; i < row_width; i++, sp++)
                      {
-                        if (*sp == trans_color->gray)
-                           *sp = (png_byte)background->gray;
+                        if (*sp == png_ptr->trans_color.gray)
+                           *sp = (png_byte)png_ptr->background.gray;
                      }
                   }
                   break;
@@ -3001,11 +2993,11 @@
 
                         v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
 
-                        if (v == trans_color->gray)
+                        if (v == png_ptr->trans_color.gray)
                         {
                            /* Background is already in screen gamma */
-                           *sp = (png_byte)((background->gray >> 8) & 0xff);
-                           *(sp + 1) = (png_byte)(background->gray & 0xff);
+                           *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
+                           *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
                         }
 
                         else
@@ -3026,10 +3018,10 @@
 
                         v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
 
-                        if (v == trans_color->gray)
+                        if (v == png_ptr->trans_color.gray)
                         {
-                           *sp = (png_byte)((background->gray >> 8) & 0xff);
-                           *(sp + 1) = (png_byte)(background->gray & 0xff);
+                           *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
+                           *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
                         }
                      }
                   }
@@ -3052,13 +3044,13 @@
                   sp = row;
                   for (i = 0; i < row_width; i++, sp += 3)
                   {
-                     if (*sp == trans_color->red &&
-                         *(sp + 1) == trans_color->green &&
-                         *(sp + 2) == trans_color->blue)
+                     if (*sp == png_ptr->trans_color.red &&
+                         *(sp + 1) == png_ptr->trans_color.green &&
+                         *(sp + 2) == png_ptr->trans_color.blue)
                      {
-                        *sp = (png_byte)background->red;
-                        *(sp + 1) = (png_byte)background->green;
-                        *(sp + 2) = (png_byte)background->blue;
+                        *sp = (png_byte)png_ptr->background.red;
+                        *(sp + 1) = (png_byte)png_ptr->background.green;
+                        *(sp + 2) = (png_byte)png_ptr->background.blue;
                      }
 
                      else
@@ -3075,13 +3067,13 @@
                   sp = row;
                   for (i = 0; i < row_width; i++, sp += 3)
                   {
-                     if (*sp == trans_color->red &&
-                         *(sp + 1) == trans_color->green &&
-                         *(sp + 2) == trans_color->blue)
+                     if (*sp == png_ptr->trans_color.red &&
+                         *(sp + 1) == png_ptr->trans_color.green &&
+                         *(sp + 2) == png_ptr->trans_color.blue)
                      {
-                        *sp = (png_byte)background->red;
-                        *(sp + 1) = (png_byte)background->green;
-                        *(sp + 2) = (png_byte)background->blue;
+                        *sp = (png_byte)png_ptr->background.red;
+                        *(sp + 1) = (png_byte)png_ptr->background.green;
+                        *(sp + 2) = (png_byte)png_ptr->background.blue;
                      }
                   }
                }
@@ -3102,16 +3094,17 @@
                      png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
                          + *(sp + 5));
 
-                     if (r == trans_color->red && g == trans_color->green &&
-                         b == trans_color->blue)
+                     if (r == png_ptr->trans_color.red &&
+                         g == png_ptr->trans_color.green &&
+                         b == png_ptr->trans_color.blue)
                      {
                         /* Background is already in screen gamma */
-                        *sp = (png_byte)((background->red >> 8) & 0xff);
-                        *(sp + 1) = (png_byte)(background->red & 0xff);
-                        *(sp + 2) = (png_byte)((background->green >> 8) & 0xff);
-                        *(sp + 3) = (png_byte)(background->green & 0xff);
-                        *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff);
-                        *(sp + 5) = (png_byte)(background->blue & 0xff);
+                        *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 + 5) = (png_byte)(png_ptr->background.blue & 0xff);
                      }
 
                      else
@@ -3145,15 +3138,16 @@
                      png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
                          + *(sp + 5));
 
-                     if (r == trans_color->red && g == trans_color->green &&
-                         b == trans_color->blue)
+                     if (r == png_ptr->trans_color.red &&
+                         g == png_ptr->trans_color.green &&
+                         b == png_ptr->trans_color.blue)
                      {
-                        *sp = (png_byte)((background->red >> 8) & 0xff);
-                        *(sp + 1) = (png_byte)(background->red & 0xff);
-                        *(sp + 2) = (png_byte)((background->green >> 8) & 0xff);
-                        *(sp + 3) = (png_byte)(background->green & 0xff);
-                        *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff);
-                        *(sp + 5) = (png_byte)(background->blue & 0xff);
+                        *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 + 5) = (png_byte)(png_ptr->background.blue & 0xff);
                      }
                   }
                }
@@ -3181,7 +3175,7 @@
                      else if (a == 0)
                      {
                         /* Background is already in screen gamma */
-                        *dp = (png_byte)background->gray;
+                        *dp = (png_byte)png_ptr->background.gray;
                      }
 
                      else
@@ -3189,7 +3183,7 @@
                         png_byte v, w;
 
                         v = gamma_to_1[*sp];
-                        png_composite(w, v, a, background_1->gray);
+                        png_composite(w, v, a, png_ptr->background_1.gray);
                         *dp = gamma_from_1[w];
                      }
                   }
@@ -3208,13 +3202,13 @@
 
 #ifdef PNG_READ_GAMMA_SUPPORTED
                      else if (a == 0)
-                        *dp = (png_byte)background->gray;
+                        *dp = (png_byte)png_ptr->background.gray;
 
                      else
-                        png_composite(*dp, *sp, a, background_1->gray);
+                        png_composite(*dp, *sp, a, png_ptr->background_1.gray);
 
 #else
-                     *dp = (png_byte)background->gray;
+                     *dp = (png_byte)png_ptr->background.gray;
 #endif
                   }
                }
@@ -3248,8 +3242,8 @@
 #endif
                      {
                         /* Background is already in screen gamma */
-                        *dp = (png_byte)((background->gray >> 8) & 0xff);
-                        *(dp + 1) = (png_byte)(background->gray & 0xff);
+                        *dp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
+                        *(dp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
                      }
 
 #ifdef PNG_READ_GAMMA_SUPPORTED
@@ -3258,7 +3252,7 @@
                         png_uint_16 g, v, w;
 
                         g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
-                        png_composite_16(v, g, a, background_1->gray);
+                        png_composite_16(v, g, a, png_ptr->background_1.gray);
                         w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8];
                         *dp = (png_byte)((w >> 8) & 0xff);
                         *(dp + 1) = (png_byte)(w & 0xff);
@@ -3285,8 +3279,8 @@
                      else
 #endif
                      {
-                        *dp = (png_byte)((background->gray >> 8) & 0xff);
-                        *(dp + 1) = (png_byte)(background->gray & 0xff);
+                        *dp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
+                        *(dp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
                      }
 
 #ifdef PNG_READ_GAMMA_SUPPORTED
@@ -3295,7 +3289,7 @@
                         png_uint_16 g, v;
 
                         g = (png_uint_16)(((*sp) << 8) + *(sp + 1));
-                        png_composite_16(v, g, a, background_1->gray);
+                        png_composite_16(v, g, a, png_ptr->background_1.gray);
                         *dp = (png_byte)((v >> 8) & 0xff);
                         *(dp + 1) = (png_byte)(v & 0xff);
                      }
@@ -3330,9 +3324,9 @@
                      else if (a == 0)
                      {
                         /* Background is already in screen gamma */
-                        *dp = (png_byte)background->red;
-                        *(dp + 1) = (png_byte)background->green;
-                        *(dp + 2) = (png_byte)background->blue;
+                        *dp = (png_byte)png_ptr->background.red;
+                        *(dp + 1) = (png_byte)png_ptr->background.green;
+                        *(dp + 2) = (png_byte)png_ptr->background.blue;
                      }
 
                      else
@@ -3340,15 +3334,15 @@
                         png_byte v, w;
 
                         v = gamma_to_1[*sp];
-                        png_composite(w, v, a, background_1->red);
+                        png_composite(w, v, a, png_ptr->background_1.red);
                         *dp = gamma_from_1[w];
 
                         v = gamma_to_1[*(sp + 1)];
-                        png_composite(w, v, a, background_1->green);
+                        png_composite(w, v, a, png_ptr->background_1.green);
                         *(dp + 1) = gamma_from_1[w];
 
                         v = gamma_to_1[*(sp + 2)];
-                        png_composite(w, v, a, background_1->blue);
+                        png_composite(w, v, a, png_ptr->background_1.blue);
                         *(dp + 2) = gamma_from_1[w];
                      }
                   }
@@ -3371,20 +3365,20 @@
 
                      else if (a == 0)
                      {
-                        *dp = (png_byte)background->red;
-                        *(dp + 1) = (png_byte)background->green;
-                        *(dp + 2) = (png_byte)background->blue;
+                        *dp = (png_byte)png_ptr->background.red;
+                        *(dp + 1) = (png_byte)png_ptr->background.green;
+                        *(dp + 2) = (png_byte)png_ptr->background.blue;
                      }
 
                      else
                      {
-                        png_composite(*dp, *sp, a, background->red);
+                        png_composite(*dp, *sp, a, png_ptr->background.red);
 
                         png_composite(*(dp + 1), *(sp + 1), a,
-                            background->green);
+                            png_ptr->background.green);
 
                         png_composite(*(dp + 2), *(sp + 2), a,
-                            background->blue);
+                            png_ptr->background.blue);
                      }
                   }
                }
@@ -3422,12 +3416,12 @@
                      else if (a == 0)
                      {
                         /* Background is already in screen gamma */
-                        *dp = (png_byte)((background->red >> 8) & 0xff);
-                        *(dp + 1) = (png_byte)(background->red & 0xff);
-                        *(dp + 2) = (png_byte)((background->green >> 8) & 0xff);
-                        *(dp + 3) = (png_byte)(background->green & 0xff);
-                        *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff);
-                        *(dp + 5) = (png_byte)(background->blue & 0xff);
+                        *dp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
+                        *(dp + 1) = (png_byte)(png_ptr->background.red & 0xff);
+                        *(dp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff);
+                        *(dp + 3) = (png_byte)(png_ptr->background.green & 0xff);
+                        *(dp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff);
+                        *(dp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
                      }
 
                      else
@@ -3435,21 +3429,21 @@
                         png_uint_16 v, w, x;
 
                         v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
-                        png_composite_16(w, v, a, background_1->red);
+                        png_composite_16(w, v, a, png_ptr->background_1.red);
 
                         x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
                         *dp = (png_byte)((x >> 8) & 0xff);
                         *(dp + 1) = (png_byte)(x & 0xff);
 
                         v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)];
-                        png_composite_16(w, v, a, background_1->green);
+                        png_composite_16(w, v, a, png_ptr->background_1.green);
 
                         x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
                         *(dp + 2) = (png_byte)((x >> 8) & 0xff);
                         *(dp + 3) = (png_byte)(x & 0xff);
 
                         v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)];
-                        png_composite_16(w, v, a, background_1->blue);
+                        png_composite_16(w, v, a, png_ptr->background_1.blue);
 
                         x = gamma_16_from_1[(w & 0xff) >> gamma_shift][w >> 8];
                         *(dp + 4) = (png_byte)((x >> 8) & 0xff);
@@ -3475,12 +3469,12 @@
 
                      else if (a == 0)
                      {
-                        *dp = (png_byte)((background->red >> 8) & 0xff);
-                        *(dp + 1) = (png_byte)(background->red & 0xff);
-                        *(dp + 2) = (png_byte)((background->green >> 8) & 0xff);
-                        *(dp + 3) = (png_byte)(background->green & 0xff);
-                        *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff);
-                        *(dp + 5) = (png_byte)(background->blue & 0xff);
+                        *dp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
+                        *(dp + 1) = (png_byte)(png_ptr->background.red & 0xff);
+                        *(dp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff);
+                        *(dp + 3) = (png_byte)(png_ptr->background.green & 0xff);
+                        *(dp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff);
+                        *(dp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
                      }
 
                      else
@@ -3493,15 +3487,15 @@
                         png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
                             + *(sp + 5));
 
-                        png_composite_16(v, r, a, background->red);
+                        png_composite_16(v, r, a, png_ptr->background.red);
                         *dp = (png_byte)((v >> 8) & 0xff);
                         *(dp + 1) = (png_byte)(v & 0xff);
 
-                        png_composite_16(v, g, a, background->green);
+                        png_composite_16(v, g, a, png_ptr->background.green);
                         *(dp + 2) = (png_byte)((v >> 8) & 0xff);
                         *(dp + 3) = (png_byte)(v & 0xff);
 
-                        png_composite_16(v, b, a, background->blue);
+                        png_composite_16(v, b, a, png_ptr->background.blue);
                         *(dp + 4) = (png_byte)((v >> 8) & 0xff);
                         *(dp + 5) = (png_byte)(v & 0xff);
                      }
@@ -3536,10 +3530,12 @@
  * build_gamma_table().
  */
 void /* PRIVATE */
-png_do_gamma(png_row_infop row_info, png_bytep row,
-    png_const_bytep gamma_table, png_const_uint_16pp gamma_16_table,
-    int gamma_shift)
+png_do_gamma(png_row_infop row_info, png_bytep row, png_structp png_ptr)
 {
+   png_const_bytep gamma_table = png_ptr->gamma_table;
+   png_const_uint_16pp gamma_16_table = png_ptr->gamma_16_table;
+   int gamma_shift = png_ptr->gamma_shift;
+
    png_bytep sp;
    png_uint_32 i;
    png_uint_32 row_width=row_info->width;
@@ -4236,6 +4232,7 @@
    }
 }
 #endif /* PNG_READ_QUANTIZE_SUPPORTED */
+#endif /* PNG_READ_TRANSFORMS_SUPPORTED */
 
 #ifdef PNG_MNG_FEATURES_SUPPORTED
 /* Undoes intrapixel differencing  */
diff --git a/pngrutil.c b/pngrutil.c
index 5b0ebce..f73021b 100644
--- a/pngrutil.c
+++ b/pngrutil.c
@@ -3397,7 +3397,9 @@
 
    png_debug(1, "in png_read_start_row");
    png_ptr->zstream.avail_in = 0;
+#ifdef PNG_READ_TRANSFORMS_SUPPORTED
    png_init_read_transformations(png_ptr);
+#endif
 #ifdef PNG_READ_INTERLACING_SUPPORTED
    if (png_ptr->interlaced)
    {
diff --git a/pngvalid.c b/pngvalid.c
index 54c55dd..116184b 100644
--- a/pngvalid.c
+++ b/pngvalid.c
@@ -108,6 +108,7 @@
    return safecat(buffer, bufsize, pos, number);
 }
 
+#ifdef PNG_READ_TRANSFORMS_SUPPORTED
 static size_t safecatd(char *buffer, size_t bufsize, size_t pos, double d,
     int precision)
 {
@@ -115,6 +116,7 @@
    sprintf(number, "%.*f", precision, d);
    return safecat(buffer, bufsize, pos, number);
 }
+#endif
 
 static PNG_CONST char invalid[] = "invalid";
 static PNG_CONST char sep[] = ": ";
@@ -225,6 +227,7 @@
 #  define READ_BDHI 3
 #endif
 
+#ifdef PNG_READ_TRANSFORMS_SUPPORTED
 static int
 next_format(png_bytep colour_type, png_bytep bit_depth)
 {
@@ -308,6 +311,7 @@
    bit_index &= 7;
    return (result >> (8-bit_index-bit_depth)) & ((1U<<bit_depth)-1);
 }
+#endif /* PNG_READ_TRANSFORMS_SUPPORTED */
 
 /* Copy a single pixel, of a given size, from one buffer to another -
  * while this is basically bit addressed there is an implicit assumption
@@ -489,6 +493,7 @@
    }
 }
 
+#ifdef PNG_READ_TRANSFORMS_SUPPORTED
 /* Use this for random 32 bit values, this function makes sure the result is
  * non-zero.
  */
@@ -508,6 +513,7 @@
          return result;
    }
 }
+#endif
 
 static void
 store_pool_init(png_store *ps, store_pool *pool)
@@ -789,6 +795,7 @@
    return ps->current->datacount;
 }
 
+#ifdef PNG_READ_TRANSFORMS_SUPPORTED
 /* Return total bytes available for read. */
 static size_t
 store_read_buffer_avail(png_store *ps)
@@ -813,6 +820,7 @@
 
    return 0;
 }
+#endif
 
 static int
 store_read_buffer_next(png_store *ps)
@@ -1358,35 +1366,6 @@
    png_byte                 buffer[1024];
 } png_modifier;
 
-static double abserr(png_modifier *pm, png_byte bit_depth)
-{
-   return bit_depth == 16 ? pm->maxabs16 : pm->maxabs8;
-}
-
-static double pcerr(png_modifier *pm, png_byte bit_depth)
-{
-   return (bit_depth == 16 ? pm->maxpc16 : pm->maxpc8) * .01;
-}
-
-static double outerr(png_modifier *pm, png_byte bit_depth)
-{
-   /* There is a serious error in the 2 and 4 bit grayscale transform because
-    * the gamma table value (8 bits) is simply shifted, not rounded, so the
-    * error in 4 bit greyscale gamma is up to the value below.  This is a hack
-    * to allow pngvalid to succeed:
-    */
-   if (bit_depth == 2)
-      return .73182-.5;
-
-   if (bit_depth == 4)
-      return .90644-.5;
-
-   if (bit_depth == 16)
-     return pm->maxout16;
-
-   return pm->maxout8;
-}
-
 /* This returns true if the test should be stopped now because it has already
  * failed and it is running silently.
  */
@@ -1424,6 +1403,36 @@
    /* Rely on the memset for all the other fields - there are no pointers */
 }
 
+#ifdef PNG_READ_TRANSFORMS_SUPPORTED
+static double abserr(png_modifier *pm, png_byte bit_depth)
+{
+   return bit_depth == 16 ? pm->maxabs16 : pm->maxabs8;
+}
+
+static double pcerr(png_modifier *pm, png_byte bit_depth)
+{
+   return (bit_depth == 16 ? pm->maxpc16 : pm->maxpc8) * .01;
+}
+
+static double outerr(png_modifier *pm, png_byte bit_depth)
+{
+   /* There is a serious error in the 2 and 4 bit grayscale transform because
+    * the gamma table value (8 bits) is simply shifted, not rounded, so the
+    * error in 4 bit greyscale gamma is up to the value below.  This is a hack
+    * to allow pngvalid to succeed:
+    */
+   if (bit_depth == 2)
+      return .73182-.5;
+
+   if (bit_depth == 4)
+      return .90644-.5;
+
+   if (bit_depth == 16)
+     return pm->maxout16;
+
+   return pm->maxout8;
+}
+
 /* One modification structure must be provided for each chunk to be modified (in
  * fact more than one can be provided if multiple separate changes are desired
  * for a single chunk.)  Modifications include adding a new chunk when a
@@ -1813,6 +1822,7 @@
 
    return set_store_for_read(&pm->this, ppi, id, name);
 }
+#endif /* PNG_READ_TRANSFORMS_SUPPORTED */
 
 /***************************** STANDARD PNG FILES *****************************/
 /* Standard files - write and save standard files. */
@@ -2748,7 +2758,7 @@
    dp->ps = ps;
    dp->colour_type = COL_FROM_ID(id);
    dp->bit_depth = DEPTH_FROM_ID(id);
-   dp->alpha_sBIT = dp->blue_sBIT = dp->green_sBIT = dp->alpha_sBIT =
+   dp->red_sBIT = dp->blue_sBIT = dp->green_sBIT = dp->alpha_sBIT =
       dp->bit_depth;
    dp->interlace_type = INTERLACE_FROM_ID(id);
    dp->id = id;
@@ -2765,7 +2775,6 @@
    memset(&dp->transparent, 0, sizeof dp->transparent);
    /* Preset the palette to full intensity/opaque througout: */
    memset(dp->palette, 0xff, sizeof dp->palette);
-
 }
 
 /* Call this only if the colour type is 3 - PNG_COLOR_TYPE_PALETTE - otherwise
@@ -3073,12 +3082,14 @@
        */
       if (dp->do_interlace && dp->interlace_type == PNG_INTERLACE_ADAM7)
       {
+#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED
          /* Use this opportunity to validate the png 'current' APIs: */
          if (y != png_get_current_row_number(pp))
             png_error(pp, "png_get_current_row_number is broken");
 
          if (pass != png_get_current_pass_number(pp))
             png_error(pp, "png_get_current_pass_number is broken");
+#endif
 
          y = PNG_ROW_FROM_PASS_ROW(y, pass);
       }
@@ -3471,6 +3482,7 @@
 
 
 /******************************* TRANSFORM TESTS ******************************/
+#ifdef PNG_READ_TRANSFORMS_SUPPORTED
 /* A set of tests to validate libpng image transforms.  The possibilities here
  * are legion because the transforms can be combined in a combinatorial
  * fashion.  To deal with this some measure of restraint is required, otherwise
@@ -4010,12 +4022,13 @@
    /* Compare the scaled, digitzed, values of our local calculation (in+-err)
     * with the digitized values libpng produced;  'sample_depth' is the actual
     * digitization depth of the libpng output colors (the bit depth except for
-    * palette images where it is always 8.)
+    * palette images where it is always 8.)  The check on 'err' is to detect
+    * internal errors in pngvalid itself (the threshold is about 1/255.)
     */
    unsigned int max = (1U<<sample_depth)-1;
    double in_min = ceil((in-err)*max - .5);
    double in_max = floor((in+err)*max + .5);
-   if (!(out >= in_min && out <= in_max))
+   if (err > 4E-3 || !(out >= in_min && out <= in_max))
    {
       char message[256];
       size_t pos;
@@ -4228,12 +4241,12 @@
 
 /* The transforms: */
 #define ITSTRUCT(name) image_transform_##name
-#define IT(name,prev)\
+#define IT(name)\
 static image_transform ITSTRUCT(name) =\
 {\
    #name,\
    1, /*enable*/\
-   &ITSTRUCT(prev), /*list*/\
+   &PT, /*list*/\
    0, /*global_use*/\
    0, /*local_use*/\
    0, /*next*/\
@@ -4241,6 +4254,7 @@
    image_transform_png_set_##name##_mod,\
    image_transform_png_set_##name##_add\
 }
+#define PT ITSTRUCT(end) /* stores the previous transform */
 
 /* To save code: */
 static int
@@ -4256,6 +4270,7 @@
    return 1;
 }
 
+#ifdef PNG_READ_EXPAND_SUPPORTED
 /* png_set_palette_to_rgb */
 static void
 image_transform_png_set_palette_to_rgb_set(PNG_CONST image_transform *this,
@@ -4287,9 +4302,12 @@
    return colour_type == PNG_COLOR_TYPE_PALETTE;
 }
 
-IT(palette_to_rgb, end);
+IT(palette_to_rgb);
+#undef PT
+#define PT ITSTRUCT(palette_to_rgb)
+#endif /* PNG_READ_EXPAND_SUPPORTED */
 
-
+#ifdef PNG_READ_EXPAND_SUPPORTED
 /* png_set_tRNS_to_alpha */
 static void
 image_transform_png_set_tRNS_to_alpha_set(PNG_CONST image_transform *this,
@@ -4341,8 +4359,12 @@
    return (colour_type & PNG_COLOR_MASK_ALPHA) == 0;
 }
 
-IT(tRNS_to_alpha,palette_to_rgb);
+IT(tRNS_to_alpha);
+#undef PT
+#define PT ITSTRUCT(tRNS_to_alpha)
+#endif /* PNG_READ_EXPAND_SUPPORTED */
 
+#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
 /* png_set_gray_to_rgb */
 static void
 image_transform_png_set_gray_to_rgb_set(PNG_CONST image_transform *this,
@@ -4395,8 +4417,12 @@
    return (colour_type & PNG_COLOR_MASK_COLOR) == 0;
 }
 
-IT(gray_to_rgb,tRNS_to_alpha);
+IT(gray_to_rgb);
+#undef PT
+#define PT ITSTRUCT(gray_to_rgb)
+#endif /* PNG_READ_GRAY_TO_RGB_SUPPORTED */
 
+#ifdef PNG_READ_EXPAND_SUPPORTED
 /* png_set_expand */
 static void
 image_transform_png_set_expand_set(PNG_CONST image_transform *this,
@@ -4437,8 +4463,12 @@
    return (colour_type & PNG_COLOR_MASK_ALPHA) == 0;
 }
 
-IT(expand,gray_to_rgb);
+IT(expand);
+#undef PT
+#define PT ITSTRUCT(expand)
+#endif /* PNG_READ_EXPAND_SUPPORTED */
 
+#ifdef PNG_READ_EXPAND_SUPPORTED
 /* png_set_expand_gray_1_2_4_to_8
  * LIBPNG BUG: this just does an 'expand'
  */
@@ -4467,7 +4497,12 @@
       bit_depth);
 }
 
-IT(expand_gray_1_2_4_to_8, expand);
+IT(expand_gray_1_2_4_to_8);
+#undef PT
+#define PT ITSTRUCT(expand_gray_1_2_4_to_8)
+#endif /* PNG_READ_EXPAND_SUPPORTED */
+
+#ifdef PNG_READ_EXPAND_16_SUPPORTED
 /* png_set_expand_16 */
 static void
 image_transform_png_set_expand_16_set(PNG_CONST image_transform *this,
@@ -4509,8 +4544,12 @@
    return bit_depth < 16;
 }
 
-IT(expand_16, expand_gray_1_2_4_to_8);
+IT(expand_16);
+#undef PT
+#define PT ITSTRUCT(expand_16)
+#endif /* PNG_READ_EXPAND_16_SUPPORTED */
 
+#ifdef PNG_READ_16_TO_8_SUPPORTED
 /* png_set_strip_16 */
 static void
 image_transform_png_set_strip_16_set(PNG_CONST image_transform *this,
@@ -4561,8 +4600,12 @@
    return bit_depth > 8;
 }
 
-IT(strip_16, expand_16);
+IT(strip_16);
+#undef PT
+#define PT ITSTRUCT(strip_16)
+#endif /* PNG_READ_16_TO_8_SUPPORTED */
 
+#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
 /* png_set_strip_alpha */
 static void
 image_transform_png_set_strip_alpha_set(PNG_CONST image_transform *this,
@@ -4600,8 +4643,12 @@
    return (colour_type & PNG_COLOR_MASK_ALPHA) != 0;
 }
 
-IT(strip_alpha,strip_16);
+IT(strip_alpha);
+#undef PT
+#define PT ITSTRUCT(strip_alpha)
+#endif /* PNG_READ_STRIP_ALPHA_SUPPORTED */
 
+#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
 /* png_set_rgb_to_gray(png_structp, int err_action, double red, double green)
  * png_set_rgb_to_gray_fixed(png_structp, int err_action, png_fixed_point red,
  *    png_fixed_point green)
@@ -4677,8 +4724,12 @@
    return (colour_type & PNG_COLOR_MASK_COLOR) != 0;
 }
 
-IT(rgb_to_gray,strip_alpha);
+IT(rgb_to_gray);
+#undef PT
+#define PT ITSTRUCT(rgb_to_gray)
+#endif /* PNG_READ_RGB_TO_GRAY_SUPPORTED */
 
+#ifdef PNG_READ_BACKGROUND_SUPPORTED
 /* png_set_background(png_structp, png_const_color_16p background_color,
  *    int background_gamma_code, int need_expand, double background_gamma)
  * png_set_background_fixed(png_structp, png_const_color_16p background_color,
@@ -4760,9 +4811,13 @@
 
 #define image_transform_png_set_background_add image_transform_default_add
 
-IT(background,rgb_to_gray);
+IT(background);
+#undef PT
+#define PT ITSTRUCT(background)
+#endif /* PNG_READ_BACKGROUND_SUPPORTED */
 
-static image_transform *PNG_CONST image_transform_first = &ITSTRUCT(background);
+/* This may just be 'end' if all the transforms are disabled! */
+static image_transform *PNG_CONST image_transform_first = &PT;
 
 static void
 transform_enable(PNG_CONST char *name)
@@ -5071,9 +5126,11 @@
    if (!test_transform(pm, 6, 3, READ_BDHI, 1))
       return;
 }
+#endif /* PNG_READ_TRANSFORMS_SUPPORTED */
 
 
 /********************************* GAMMA TESTS ********************************/
+#ifdef PNG_READ_GAMMA_SUPPORTED
 /* Gamma test images. */
 typedef struct gamma_modification
 {
@@ -6016,6 +6073,7 @@
    }
 #endif
 }
+#endif /* PNG_READ_GAMMA_SUPPORTED */
 
 /* INTERLACE MACRO VALIDATION */
 /* This is copied verbatim from the specification, it is simply the pass
@@ -6467,6 +6525,7 @@
       else if (strcmp(*argv, "--notransform") == 0)
          pm.test_transform = 0;
 
+#ifdef PNG_READ_TRANSFORMS_SUPPORTED
       else if (strncmp(*argv, "--transform-disable=",
          sizeof "--transform-disable") == 0)
          {
@@ -6480,6 +6539,7 @@
          pm.test_transform = 1;
          transform_enable(*argv + sizeof "--transform-enable");
          }
+#endif /* PNG_READ_TRANSFORMS_SUPPORTED */
 
       else if (strcmp(*argv, "--gamma") == 0)
          {
@@ -6620,13 +6680,17 @@
          perform_size_test(&pm);
       }
 
+#ifdef PNG_READ_TRANSFORMS_SUPPORTED
       /* Combinatorial transforms: */
       if (pm.test_transform)
          perform_transform_test(&pm);
+#endif /* PNG_READ_TRANSFORMS_SUPPORTED */
 
+#ifdef PNG_READ_GAMMA_SUPPORTED
       if (pm.ngammas > 0)
          perform_gamma_test(&pm, pm.this.speed != 0,
             summary && !pm.this.speed);
+#endif
    }
 
    Catch(fault)
diff --git a/pngwrite.c b/pngwrite.c
index 7b7b10d..bce00c0 100644
--- a/pngwrite.c
+++ b/pngwrite.c
@@ -805,9 +805,11 @@
    }
 #endif
 
+#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED
    /* Handle other transformations */
    if (png_ptr->transformations)
       png_do_write_transformations(png_ptr);
+#endif
 
 #ifdef PNG_MNG_FEATURES_SUPPORTED
    /* Write filter_method 64 (intrapixel differencing) only if
diff --git a/pngwtran.c b/pngwtran.c
index 2473d14..a5003d0 100644
--- a/pngwtran.c
+++ b/pngwtran.c
@@ -15,6 +15,7 @@
 
 #ifdef PNG_WRITE_SUPPORTED
 
+#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED
 /* Transform the data according to the user's wishes.  The order of
  * transformations is significant.
  */
@@ -563,6 +564,7 @@
    }
 }
 #endif
+#endif /* PNG_WRITE_TRANSFORMS_SUPPORTED */
 
 #ifdef PNG_MNG_FEATURES_SUPPORTED
 /* Undoes intrapixel differencing  */
diff --git a/scripts/pnglibconf.dfa b/scripts/pnglibconf.dfa
index a5c2048..71aab33 100644
--- a/scripts/pnglibconf.dfa
+++ b/scripts/pnglibconf.dfa
@@ -340,6 +340,10 @@
 option INCH_CONVERSIONS
 = INCH_CONVERSIONS INCH_CONVERSIONS
 
+# API to build a grayscale palette
+
+option BUILD_GRAYSCALE_PALETTE
+
 # IN DEVELOPMENT
 # These are currently experimental features, define them if you want
 
diff --git a/scripts/pnglibconf.h.prebuilt b/scripts/pnglibconf.h.prebuilt
index a276502..b240c34 100644
--- a/scripts/pnglibconf.h.prebuilt
+++ b/scripts/pnglibconf.h.prebuilt
@@ -43,6 +43,7 @@
 #define PNG_ALIGN_MEMORY_SUPPORTED
 #define PNG_BENIGN_ERRORS_SUPPORTED
 #define PNG_bKGD_SUPPORTED
+#define PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED
 #define PNG_CHECK_cHRM_SUPPORTED
 #define PNG_cHRM_SUPPORTED
 #define PNG_CONSOLE_IO_SUPPORTED