From 2af4d8caace542fca1e65a0d8e4ece3b1a217948 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Mon, 6 Jan 2025 13:02:10 +0100 Subject: [PATCH] Fix libgd 223: gdImageRotateGeneric() does not properly interpolate We port the respective upstream fix[1]. We only run the test against bundled libgd, since external libgd may yield different results. Cf. . --- ext/gd/libgd/gd_interpolation.c | 20 ++++---------------- ext/gd/tests/gd223.phpt | 26 ++++++++++++++++++++++++++ ext/gd/tests/gd223.png | Bin 0 -> 9721 bytes 3 files changed, 30 insertions(+), 16 deletions(-) create mode 100644 ext/gd/tests/gd223.phpt create mode 100644 ext/gd/tests/gd223.png diff --git a/ext/gd/libgd/gd_interpolation.c b/ext/gd/libgd/gd_interpolation.c index 4b1583a8d6e82..bc1b3d344e69e 100644 --- a/ext/gd/libgd/gd_interpolation.c +++ b/ext/gd/libgd/gd_interpolation.c @@ -748,8 +748,8 @@ static int getPixelInterpolateWeight(gdImagePtr im, const double x, const double */ int getPixelInterpolated(gdImagePtr im, const double x, const double y, const int bgColor) { - const int xi=(int)((x) < 0 ? x - 1: x); - const int yi=(int)((y) < 0 ? y - 1: y); + const int xi=(int)(x); + const int yi=(int)(y); int yii; int i; double kernel, kernel_cache_y; @@ -1713,13 +1713,6 @@ gdImagePtr gdImageRotateGeneric(gdImagePtr src, const float degrees, const int b int new_width, new_height; gdRect bbox; - const gdFixed f_slop_y = f_sin; - const gdFixed f_slop_x = f_cos; - const gdFixed f_slop = f_slop_x > 0 && f_slop_y > 0 ? - (f_slop_x > f_slop_y ? gd_divfx(f_slop_y, f_slop_x) : gd_divfx(f_slop_x, f_slop_y)) - : 0; - - if (bgColor < 0) { return NULL; } @@ -1745,15 +1738,10 @@ gdImagePtr gdImageRotateGeneric(gdImagePtr src, const float degrees, const int b long m = gd_fxtoi(f_m); long n = gd_fxtoi(f_n); - if ((n <= 0) || (m <= 0) || (m >= src_h) || (n >= src_w)) { + if (m < -1 || n < -1 || m >= src_h || n >= src_w ) { dst->tpixels[dst_offset_y][dst_offset_x++] = bgColor; - } else if ((n <= 1) || (m <= 1) || (m >= src_h - 1) || (n >= src_w - 1)) { - register int c = getPixelInterpolated(src, n, m, bgColor); - c = c | (( gdTrueColorGetAlpha(c) + ((int)(127* gd_fxtof(f_slop)))) << 24); - - dst->tpixels[dst_offset_y][dst_offset_x++] = _color_blend(bgColor, c); } else { - dst->tpixels[dst_offset_y][dst_offset_x++] = getPixelInterpolated(src, n, m, bgColor); + dst->tpixels[dst_offset_y][dst_offset_x++] = getPixelInterpolated(src, gd_fxtod(f_n), gd_fxtod(f_m), bgColor); } } dst_offset_y++; diff --git a/ext/gd/tests/gd223.phpt b/ext/gd/tests/gd223.phpt new file mode 100644 index 0000000000000..c378ab199ac50 --- /dev/null +++ b/ext/gd/tests/gd223.phpt @@ -0,0 +1,26 @@ +--TEST-- +libgd bug 223 (gdImageRotateGeneric() does not properly interpolate) +--EXTENSIONS-- +gd +--SKIPIF-- + +--FILE-- + +--EXPECT-- +The images are equal. diff --git a/ext/gd/tests/gd223.png b/ext/gd/tests/gd223.png new file mode 100644 index 0000000000000000000000000000000000000000..02e10e2cc3a13c8adc43b00ac7441bd6d83959f7 GIT binary patch literal 9721 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 XOpUP)>2o#sEEhsuSx2c#!7Ac^)=i)y literal 0 HcmV?d00001