[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