From d371f5f518e9c703a0091791fb3d45564086e663 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Tue, 6 Dec 2022 14:41:32 +0100 Subject: [PATCH] =?UTF-8?q?imagesavealpha(=E2=80=A6,=20false)=20should=20n?= =?UTF-8?q?ot=20save=20alpha=20channel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While this is properly handled for PNG images, it is apparently not for WebP and AVIF so far. Noticed due to . --- ext/gd/libgd/gd_avif.c | 7 +++- ext/gd/libgd/gd_webp.c | 39 +++++++++++++++------ ext/gd/tests/imagesavealpha_avif.phpt | 50 +++++++++++++++++++++++++++ ext/gd/tests/imagesavealpha_png.phpt | 50 +++++++++++++++++++++++++++ ext/gd/tests/imagesavealpha_webp.phpt | 50 +++++++++++++++++++++++++++ 5 files changed, 184 insertions(+), 12 deletions(-) create mode 100644 ext/gd/tests/imagesavealpha_avif.phpt create mode 100644 ext/gd/tests/imagesavealpha_png.phpt create mode 100644 ext/gd/tests/imagesavealpha_webp.phpt diff --git a/ext/gd/libgd/gd_avif.c b/ext/gd/libgd/gd_avif.c index 30075d2a899c8..505736c39b484 100644 --- a/ext/gd/libgd/gd_avif.c +++ b/ext/gd/libgd/gd_avif.c @@ -528,6 +528,9 @@ void gdImageAvifCtx(gdImagePtr im, gdIOCtx *outfile, int quality, int speed) avifIm->matrixCoefficients = lossless ? AVIF_MATRIX_COEFFICIENTS_IDENTITY : AVIF_MATRIX_COEFFICIENTS_BT709; avifRGBImageSetDefaults(&rgb, avifIm); + if (!im->saveAlphaFlag) { + rgb.format = AVIF_RGB_FORMAT_RGB; + } // this allocates memory, and sets rgb.rowBytes and rgb.pixels. avifRGBImageAllocatePixels(&rgb); @@ -542,7 +545,9 @@ void gdImageAvifCtx(gdImagePtr im, gdIOCtx *outfile, int quality, int speed) *(p++) = gdTrueColorGetRed(val); *(p++) = gdTrueColorGetGreen(val); *(p++) = gdTrueColorGetBlue(val); - *(p++) = alpha7BitTo8Bit(gdTrueColorGetAlpha(val)); + if (im->saveAlphaFlag) { + *(p++) = alpha7BitTo8Bit(gdTrueColorGetAlpha(val)); + } } } diff --git a/ext/gd/libgd/gd_webp.c b/ext/gd/libgd/gd_webp.c index a0d8a0cf49f5c..6d82524810696 100644 --- a/ext/gd/libgd/gd_webp.c +++ b/ext/gd/libgd/gd_webp.c @@ -107,6 +107,9 @@ void gdImageWebpCtx (gdImagePtr im, gdIOCtx * outfile, int quality) uint8_t *p; uint8_t *out; size_t out_size; + uint8_t bpp; + size_t (*encode)(const uint8_t*, int, int, int, float, uint8_t**); + size_t (*encode_lossless)(const uint8_t*, int, int, int, uint8_t**); if (im == NULL) { return; @@ -121,15 +124,25 @@ void gdImageWebpCtx (gdImagePtr im, gdIOCtx * outfile, int quality) quality = 80; } - if (overflow2(gdImageSX(im), 4)) { + if (im->saveAlphaFlag) { + bpp = 4; + encode = WebPEncodeRGBA; + encode_lossless = WebPEncodeLosslessRGBA; + } else { + bpp = 3; + encode = WebPEncodeRGB; + encode_lossless = WebPEncodeLosslessRGB; + } + + if (overflow2(gdImageSX(im), bpp)) { return; } - if (overflow2(gdImageSX(im) * 4, gdImageSY(im))) { + if (overflow2(gdImageSX(im) * bpp, gdImageSY(im))) { return; } - argb = (uint8_t *)gdMalloc(gdImageSX(im) * 4 * gdImageSY(im)); + argb = (uint8_t *)gdMalloc(gdImageSX(im) * bpp * gdImageSY(im)); if (!argb) { return; } @@ -139,23 +152,27 @@ void gdImageWebpCtx (gdImagePtr im, gdIOCtx * outfile, int quality) register int c; register char a; c = im->tpixels[y][x]; - a = gdTrueColorGetAlpha(c); - if (a == 127) { - a = 0; - } else { - a = 255 - ((a << 1) + (a >> 6)); + if (bpp == 4) { + a = gdTrueColorGetAlpha(c); + if (a == 127) { + a = 0; + } else { + a = 255 - ((a << 1) + (a >> 6)); + } } *(p++) = gdTrueColorGetRed(c); *(p++) = gdTrueColorGetGreen(c); *(p++) = gdTrueColorGetBlue(c); - *(p++) = a; + if (bpp == 4) { + *(p++) = a; + } } } if (quality >= gdWebpLossless) { - out_size = WebPEncodeLosslessRGBA(argb, gdImageSX(im), gdImageSY(im), gdImageSX(im) * 4, &out); + out_size = encode_lossless(argb, gdImageSX(im), gdImageSY(im), gdImageSX(im) * bpp, &out); } else { - out_size = WebPEncodeRGBA(argb, gdImageSX(im), gdImageSY(im), gdImageSX(im) * 4, quality, &out); + out_size = encode(argb, gdImageSX(im), gdImageSY(im), gdImageSX(im) * bpp, quality, &out); } if (out_size == 0) { diff --git a/ext/gd/tests/imagesavealpha_avif.phpt b/ext/gd/tests/imagesavealpha_avif.phpt new file mode 100644 index 0000000000000..0ed840f87bd7e --- /dev/null +++ b/ext/gd/tests/imagesavealpha_avif.phpt @@ -0,0 +1,50 @@ +--TEST-- +Testing imagesavealpha() with AVIF +--EXTENSIONS-- +gd +--SKIPIF-- + +--FILE-- + +--CLEAN-- + +--EXPECT-- +without alpha +with alpha diff --git a/ext/gd/tests/imagesavealpha_png.phpt b/ext/gd/tests/imagesavealpha_png.phpt new file mode 100644 index 0000000000000..252d603f84d29 --- /dev/null +++ b/ext/gd/tests/imagesavealpha_png.phpt @@ -0,0 +1,50 @@ +--TEST-- +Testing imagesavealpha() with PNG +--EXTENSIONS-- +gd +--SKIPIF-- + +--FILE-- + +--CLEAN-- + +--EXPECT-- +without alpha +with alpha diff --git a/ext/gd/tests/imagesavealpha_webp.phpt b/ext/gd/tests/imagesavealpha_webp.phpt new file mode 100644 index 0000000000000..02b33ee710edd --- /dev/null +++ b/ext/gd/tests/imagesavealpha_webp.phpt @@ -0,0 +1,50 @@ +--TEST-- +Testing imagesavealpha() with WebP +--EXTENSIONS-- +gd +--SKIPIF-- + +--FILE-- + +--CLEAN-- + +--EXPECT-- +without alpha +with alpha