[devel] Clean up ALPHA flags and transformations
diff --git a/pngpread.c b/pngpread.c
index 7b1149b..13d4831 100644
--- a/pngpread.c
+++ b/pngpread.c
@@ -1026,7 +1026,7 @@
 
    png_memcpy(png_ptr->prev_row, png_ptr->row_buf, png_ptr->rowbytes + 1);
 
-   if (png_ptr->transformations || (png_ptr->flags&PNG_FLAG_STRIP_ALPHA))
+   if (png_ptr->transformations)
       png_do_read_transformations(png_ptr);
 
 #ifdef PNG_READ_INTERLACING_SUPPORTED
diff --git a/pngpriv.h b/pngpriv.h
index 7faa8b3..b6f382e 100644
--- a/pngpriv.h
+++ b/pngpriv.h
@@ -340,8 +340,8 @@
 #define PNG_FLAG_STRIP_ERROR_NUMBERS      0x40000L
 #define PNG_FLAG_STRIP_ERROR_TEXT         0x80000L
 #define PNG_FLAG_MALLOC_NULL_MEM_OK       0x100000L
-#define PNG_FLAG_ADD_ALPHA                0x200000L  /* Added to libpng-1.2.8 */
-#define PNG_FLAG_STRIP_ALPHA              0x400000L  /* Added to libpng-1.2.8 */
+                                  /*      0x200000L  unused */
+                                  /*      0x400000L  unused */
 #define PNG_FLAG_BENIGN_ERRORS_WARN       0x800000L  /* Added to libpng-1.4.0 */
                                   /*     0x1000000L  unused */
                                   /*     0x2000000L  unused */
@@ -772,8 +772,8 @@
 
 #if defined(PNG_WRITE_FILLER_SUPPORTED) || \
     defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
-PNG_EXTERN void png_do_strip_filler PNGARG((png_row_infop row_info,
-    png_bytep row, png_uint_32 flags));
+PNG_EXTERN void png_do_strip_channel PNGARG((png_row_infop row_info,
+    png_bytep row, int at_start));
 #endif
 
 #ifdef PNG_16BIT_SUPPORTED
diff --git a/pngread.c b/pngread.c
index 2e365cd..d8741cd 100644
--- a/pngread.c
+++ b/pngread.c
@@ -702,7 +702,7 @@
 #endif
 
 
-   if (png_ptr->transformations || (png_ptr->flags&PNG_FLAG_STRIP_ALPHA))
+   if (png_ptr->transformations)
       png_do_read_transformations(png_ptr);
 
 #ifdef PNG_READ_INTERLACING_SUPPORTED
diff --git a/pngrtran.c b/pngrtran.c
index e6e0c46..0ab3d8f 100644
--- a/pngrtran.c
+++ b/pngrtran.c
@@ -149,7 +149,7 @@
    if (png_ptr == NULL)
       return;
 
-   png_ptr->flags |= PNG_FLAG_STRIP_ALPHA;
+   png_ptr->transformations |= PNG_STRIP_ALPHA;
 }
 #endif
 
@@ -1073,7 +1073,7 @@
              */
             png_ptr->transformations &= ~PNG_BACKGROUND;
             png_ptr->transformations &= ~PNG_GAMMA;
-            png_ptr->flags |= PNG_FLAG_STRIP_ALPHA;
+            png_ptr->transformations |= PNG_STRIP_ALPHA;
          }
 
          /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */
@@ -1207,7 +1207,7 @@
 
       /* Handled alpha, still need to strip the channel. */
       png_ptr->transformations &= ~PNG_BACKGROUND;
-      png_ptr->flags |= PNG_FLAG_STRIP_ALPHA;
+      png_ptr->transformations |= PNG_STRIP_ALPHA;
    }
 #endif /* PNG_READ_BACKGROUND_SUPPORTED */
 
@@ -1353,7 +1353,7 @@
       info_ptr->channels = 1;
 
 #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
-   if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA)
+   if (png_ptr->transformations & PNG_STRIP_ALPHA)
       info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
 #endif
 
@@ -1454,9 +1454,11 @@
 #endif
 
 #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
-   if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA)
-      png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
-          PNG_FLAG_FILLER_AFTER | (png_ptr->flags & PNG_FLAG_STRIP_ALPHA));
+   if ((png_ptr->transformations & PNG_STRIP_ALPHA) &&
+      (png_ptr->row_info.color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
+      png_ptr->row_info.color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
+      png_do_strip_channel(&(png_ptr->row_info), png_ptr->row_buf + 1,
+         0/*!at_start, because SWAP_ALPHA happens later*/);
 #endif
 
 #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
diff --git a/pngtrans.c b/pngtrans.c
index 89661ad..de18478 100644
--- a/pngtrans.c
+++ b/pngtrans.c
@@ -424,170 +424,115 @@
 
 #if defined(PNG_WRITE_FILLER_SUPPORTED) || \
     defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
-/* Remove filler or alpha byte(s) */
+/* Remove a channel - this used to be 'png_do_strip_filler' but it used a
+ * somewhat weird combination of flags to determine what to do.  All the calls
+ * to png_do_strip_filler are changed in 1.5.2 to call this instead with the
+ * correct arguments.
+ *
+ * The routine isn't general - the channel must be the channel at the start or
+ * end (not in the middle) of each pixel.
+ */
 void /* PRIVATE */
-png_do_strip_filler(png_row_infop row_info, png_bytep row, png_uint_32 flags)
+png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start)
 {
-   png_debug(1, "in png_do_strip_filler");
+   png_bytep sp = row; /* source pointer */
+   png_bytep dp = row; /* destination pointer */
+   png_bytep ep = row + row_info->rowbytes; /* One beyond end of row */
 
+   /* At the start sp will point to the first byte to copy and dp to where
+    * it is copied to.  ep always points just beyond the end of the row, so
+    * the loop simply copies (channels-1) channels until sp reaches ep.
+    */
+   /* GA, GX, XG cases */
+   if (row_info->channels == 2)
    {
-      png_bytep sp = row;
-      png_bytep dp = row;
-      png_uint_32 row_width = row_info->width;
-      png_uint_32 i;
-
-      if ((row_info->color_type == PNG_COLOR_TYPE_RGB ||
-          (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
-          (flags & PNG_FLAG_STRIP_ALPHA))) &&
-          row_info->channels == 4)
+      if (row_info->bit_depth == 8)
       {
-         if (row_info->bit_depth == 8)
-         {
-            /* This converts from RGBX or RGBA to RGB */
-            if (flags & PNG_FLAG_FILLER_AFTER)
-            {
-               dp += 3; sp += 4;
-               for (i = 1; i < row_width; i++)
-               {
-                  *dp++ = *sp++;
-                  *dp++ = *sp++;
-                  *dp++ = *sp++;
-                  sp++;
-               }
-            }
+         if (at_start) /* Skip initial filler */
+            ++sp;
+         else          /* Skip initial channels and, for sp, the filler */
+            sp += 2, ++dp;
 
-            /* This converts from XRGB or ARGB to RGB */
-            else
-            {
-               for (i = 0; i < row_width; i++)
-               {
-                  sp++;
-                  *dp++ = *sp++;
-                  *dp++ = *sp++;
-                  *dp++ = *sp++;
-               }
-            }
-            row_info->pixel_depth = 24;
-            row_info->rowbytes = row_width * 3;
-         }
+         /* For a 1 pixel wide image there is nothing to do */
+         while (sp < ep)
+            *dp++ = *sp, sp += 2;
 
-         else /* if (row_info->bit_depth == 16) */
-         {
-            if (flags & PNG_FLAG_FILLER_AFTER)
-            {
-               /* This converts from RRGGBBXX or RRGGBBAA to RRGGBB */
-               sp += 8; dp += 6;
-               for (i = 1; i < row_width; i++)
-               {
-                  /* This could be (although png_memcpy is probably slower):
-                  png_memcpy(dp, sp, 6);
-                  sp += 8;
-                  dp += 6;
-                  */
-
-                  *dp++ = *sp++;
-                  *dp++ = *sp++;
-                  *dp++ = *sp++;
-                  *dp++ = *sp++;
-                  *dp++ = *sp++;
-                  *dp++ = *sp++;
-                  sp += 2;
-               }
-            }
-
-            else
-            {
-               /* This converts from XXRRGGBB or AARRGGBB to RRGGBB */
-               for (i = 0; i < row_width; i++)
-               {
-                  /* This could be (although png_memcpy is probably slower):
-                  png_memcpy(dp, sp, 6);
-                  sp += 8;
-                  dp += 6;
-                  */
-
-                  sp += 2;
-                  *dp++ = *sp++;
-                  *dp++ = *sp++;
-                  *dp++ = *sp++;
-                  *dp++ = *sp++;
-                  *dp++ = *sp++;
-                  *dp++ = *sp++;
-               }
-            }
-
-            row_info->pixel_depth = 48;
-            row_info->rowbytes = row_width * 6;
-         }
-         row_info->channels = 3;
+         row_info->pixel_depth = 8;
       }
 
-      else if ((row_info->color_type == PNG_COLOR_TYPE_GRAY ||
-         (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
-         (flags & PNG_FLAG_STRIP_ALPHA))) &&
-          row_info->channels == 2)
+      else if (row_info->bit_depth == 16)
       {
-         if (row_info->bit_depth == 8)
-         {
-            if (flags & PNG_FLAG_FILLER_AFTER)
-            {
-               /* This converts from GX or GA to G */
-               for (i = 0; i < row_width; i++)
-               {
-                  *dp++ = *sp++;
-                  sp++;
-               }
-            }
+         if (at_start)
+            sp += 2;
+         else
+            sp += 4, dp += 2;
 
-            else
-            {
-               /* This converts from XG or AG to G */
-               for (i = 0; i < row_width; i++)
-               {
-                  sp++;
-                  *dp++ = *sp++;
-               }
-            }
+         while (sp < ep)
+            *dp++ = *sp++, *dp++ = *sp, sp += 3;
 
-            row_info->pixel_depth = 8;
-            row_info->rowbytes = row_width;
-         }
-
-         else /* if (row_info->bit_depth == 16) */
-         {
-            if (flags & PNG_FLAG_FILLER_AFTER)
-            {
-               /* This converts from GGXX or GGAA to GG */
-               sp += 4; dp += 2;
-               for (i = 1; i < row_width; i++)
-               {
-                  *dp++ = *sp++;
-                  *dp++ = *sp++;
-                  sp += 2;
-               }
-            }
-
-            else
-            {
-               /* This converts from XXGG or AAGG to GG */
-               for (i = 0; i < row_width; i++)
-               {
-                  sp += 2;
-                  *dp++ = *sp++;
-                  *dp++ = *sp++;
-               }
-            }
-
-            row_info->pixel_depth = 16;
-            row_info->rowbytes = row_width * 2;
-         }
-         row_info->channels = 1;
+         row_info->pixel_depth = 16;
       }
 
-      if (flags & PNG_FLAG_STRIP_ALPHA)
-        row_info->color_type = (png_byte)(row_info->color_type &
-            ~PNG_COLOR_MASK_ALPHA);
+      else
+         return; /* bad bit depth */
+
+      row_info->channels = 1;
+
+      /* Finally fix the color type if it records an alpha channel */
+      if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+         row_info->color_type = PNG_COLOR_TYPE_GRAY;
    }
+
+   /* RGBA, RGBX, XRGB cases */
+   else if (row_info->channels == 4)
+   {
+      if (row_info->bit_depth == 8)
+      {
+         if (at_start) /* Skip initial filler */
+            ++sp;
+         else          /* Skip initial channels and, for sp, the filler */
+            sp += 4, dp += 3;
+
+         /* Note that the loop adds 3 to dp and 4 to sp each time. */
+         while (sp < ep)
+            *dp++ = *sp++, *dp++ = *sp++, *dp++ = *sp, sp += 2;
+
+         row_info->pixel_depth = 24;
+      }
+
+      else if (row_info->bit_depth == 16)
+      {
+         if (at_start)
+            sp += 2;
+         else
+            sp += 8, dp += 6;
+
+         while (sp < ep)
+         {
+            /* Copy 6 bytes, skip 2 */
+            *dp++ = *sp++, *dp++ = *sp++;
+            *dp++ = *sp++, *dp++ = *sp++;
+            *dp++ = *sp++, *dp++ = *sp, sp += 3;
+         }
+
+         row_info->pixel_depth = 48;
+      }
+
+      else
+         return; /* bad bit depth */
+
+      row_info->channels = 3;
+
+      /* Finally fix the color type if it records an alpha channel */
+      if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+         row_info->color_type = PNG_COLOR_TYPE_RGB;
+   }
+
+   else
+      return; /* The filler channel has gone already */
+
+   /* Fix the rowbytes value. */
+   row_info->rowbytes = dp-row;
 }
 #endif
 
diff --git a/pngwtran.c b/pngwtran.c
index 115ca37..ce4c549 100644
--- a/pngwtran.c
+++ b/pngwtran.c
@@ -44,8 +44,8 @@
 
 #ifdef PNG_WRITE_FILLER_SUPPORTED
    if (png_ptr->transformations & PNG_FILLER)
-      png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
-          png_ptr->flags);
+      png_do_strip_channel(&(png_ptr->row_info), png_ptr->row_buf + 1,
+         !(png_ptr->flags & PNG_FILLER_AFTER));
 #endif
 
 #ifdef PNG_WRITE_PACKSWAP_SUPPORTED