From 643a77dda356664356d44183cd696d6cfce8a683 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Mon, 23 Dec 2024 19:55:52 +0100 Subject: [PATCH] Port fix for libgd bug 276 The issue that BMP RLE occasionally swallowed some pixels[1] had been fixed long ago in libgd, but apparently it has been overlooked to port it to our bundled libgd. We also introduce the test helper `test_image_equals_image()` which compares in-memory images for equality. [1] Closes GH-17250. --- NEWS | 2 ++ ext/gd/libgd/gd_bmp.c | 4 +--- ext/gd/tests/func.inc | 28 +++++++++++++++++++++------- ext/gd/tests/gd276.phpt | 26 ++++++++++++++++++++++++++ 4 files changed, 50 insertions(+), 10 deletions(-) create mode 100644 ext/gd/tests/gd276.phpt diff --git a/NEWS b/NEWS index b89ef952f370d..730a38b648b60 100644 --- a/NEWS +++ b/NEWS @@ -41,6 +41,8 @@ PHP NEWS - GD: . Fixed bug GH-16255 (Unexpected nan value in ext/gd/libgd/gd_filter.c). (nielsdos, cmb) + . Ported fix for libgd bug 276 (Sometimes pixels are missing when storing + images as BMPs). (cmb) - Gettext: . Fixed bug GH-17202 (Segmentation fault ext/gettext/gettext.c diff --git a/ext/gd/libgd/gd_bmp.c b/ext/gd/libgd/gd_bmp.c index a80904a62914d..27b5d11ae7683 100644 --- a/ext/gd/libgd/gd_bmp.c +++ b/ext/gd/libgd/gd_bmp.c @@ -350,9 +350,7 @@ static int compress_row(unsigned char *row, int length) } if (compressed_run) { - if (rle_type == BMP_RLE_TYPE_RLE) { - compressed_length += build_rle_packet(row, rle_type, compressed_run, uncompressed_row); - } + compressed_length += build_rle_packet(row, rle_type, compressed_run, uncompressed_row); } gdFree(uncompressed_start); diff --git a/ext/gd/tests/func.inc b/ext/gd/tests/func.inc index 5273f998300b1..0f10aa7d83dee 100644 --- a/ext/gd/tests/func.inc +++ b/ext/gd/tests/func.inc @@ -70,12 +70,8 @@ function get_libxpm_version() * message is printed, and the actual file is stored right beside the temporary * .php test file with the extension .out.png, to be able to manually inspect * the result. - * - * @param string $filename - * @param resource $actual - * @return void */ -function test_image_equals_file($filename, $actual) +function test_image_equals_file(string $filename, GdImage $actual): void { if (!file_exists($filename)) { echo "The expected image does not exist.\n"; @@ -85,13 +81,29 @@ function test_image_equals_file($filename, $actual) $actual = test_to_truecolor($actual); $expected = imagecreatefrompng($filename); $expected = test_to_truecolor($expected); + test_image_equals_image($expected, $actual, true); +} + +/** + * Tests that an in-memory image equals another in-memory image. + * + * It checks for equal image sizes, and whether any pixels are different. + * The textual result is printed, so the EXPECT section should contain the line + * "The images are equal." + * + * If the images are not equal, a diagnostic message is printed. + */ +function test_image_equals_image(GdImage $expected, GdImage $actual, bool $save_actual = false): void +{ $exp_x = imagesx($expected); $exp_y = imagesy($expected); $act_x = imagesx($actual); $act_y = imagesy($actual); if ($exp_x != $act_x || $exp_y != $act_y) { echo "The image size differs: expected {$exp_x}x{$exp_y}, got {$act_x}x{$act_y}.\n"; - save_actual_image($actual); + if ($save_actual) { + save_actual_image($actual); + } return; } $pixels_changed = 0; @@ -108,7 +120,9 @@ function test_image_equals_file($filename, $actual) echo "The images are equal.\n"; } else { echo "The images differ in {$pixels_changed} pixels.\n"; - save_actual_image($actual); + if ($save_actual) { + save_actual_image($actual); + } } } diff --git a/ext/gd/tests/gd276.phpt b/ext/gd/tests/gd276.phpt new file mode 100644 index 0000000000000..a12bce3983049 --- /dev/null +++ b/ext/gd/tests/gd276.phpt @@ -0,0 +1,26 @@ +--TEST-- +libgd bug 276 (Sometimes pixels are missing when storing images as BMPs) +--EXTENSIONS-- +gd +--FILE-- + +--EXPECT-- +bool(true) +The images are equal. +--CLEAN-- +