Skip to content

Commit

Permalink
Port fix for libgd bug 276
Browse files Browse the repository at this point in the history
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] <libgd/libgd#276>

Closes GH-17250.
  • Loading branch information
cmb69 committed Dec 25, 2024
1 parent a24eada commit 643a77d
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 10 deletions.
2 changes: 2 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 1 addition & 3 deletions ext/gd/libgd/gd_bmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
28 changes: 21 additions & 7 deletions ext/gd/tests/func.inc
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -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;
Expand All @@ -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);
}
}
}

Expand Down
26 changes: 26 additions & 0 deletions ext/gd/tests/gd276.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
--TEST--
libgd bug 276 (Sometimes pixels are missing when storing images as BMPs)
--EXTENSIONS--
gd
--FILE--
<?php
require __DIR__ . "/func.inc";

$orig = imagecreate(10, 10);
imagecolorallocate($orig, 0, 0, 0);
$white = imagecolorallocate($orig, 255, 255, 255);
imageline($orig, 0, 0, 99, 99, $white);

$filename = __DIR__ . "/gd276.bmp";
imagebmp($orig, $filename, true);
$saved = imagecreatefrombmp($filename);
var_dump($saved !== false);
test_image_equals_image($orig, $saved);
?>
--EXPECT--
bool(true)
The images are equal.
--CLEAN--
<?php
@unlink(__DIR__ . "/gd276.bmp");
?>

0 comments on commit 643a77d

Please sign in to comment.