Skip to content

Implement slow GD test helpers in C #17305

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/actions/configure-x32/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ runs:

export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:/usr/lib/i386-linux-gnu/pkgconfig"
./buildconf --force
export CFLAGS="-m32 -msse2"
export CFLAGS="-m32 -msse2 -DGD_TEST_HELPERS"
export CXXFLAGS="-m32 -msse2"
export LDFLAGS=-L/usr/lib/i386-linux-gnu
./configure ${{ inputs.configurationParameters }} \
Expand Down
2 changes: 1 addition & 1 deletion .github/scripts/windows/build_task.bat
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ if "%THREAD_SAFE%" equ "0" set ADD_CONF=%ADD_CONF% --disable-zts
if "%INTRINSICS%" neq "" set ADD_CONF=%ADD_CONF% --enable-native-intrinsics=%INTRINSICS%
if "%ASAN%" equ "1" set ADD_CONF=%ADD_CONF% --enable-sanitizer --enable-debug-pack

set CFLAGS=/W1 /WX /w14013
set CFLAGS=/W1 /WX /w14013 /DGD_TEST_HELPERS

cmd /c configure.bat ^
--enable-snapshot-build ^
Expand Down
67 changes: 67 additions & 0 deletions ext/gd/gd.c
Original file line number Diff line number Diff line change
Expand Up @@ -4326,6 +4326,73 @@ PHP_FUNCTION(imageresolution)
}
/* }}} */

#ifdef GD_TEST_HELPERS
static PHP_FUNCTION(imagechangedpixels)
{
zval *IM1, *IM2;
gdImagePtr im1, im2;
int i, j, result = 0;

ZEND_PARSE_PARAMETERS_START(2, 2)
Z_PARAM_OBJECT_OF_CLASS(IM1, gd_image_ce)
Z_PARAM_OBJECT_OF_CLASS(IM2, gd_image_ce)
ZEND_PARSE_PARAMETERS_END();

im1 = php_gd_libgdimageptr_from_zval_p(IM1);
im2 = php_gd_libgdimageptr_from_zval_p(IM2);

ZEND_ASSERT(gdImageTrueColor(im1) && gdImageTrueColor(im2));
ZEND_ASSERT(gdImageSX(im1) == gdImageSX(im2) && gdImageSY(im1) == gdImageSY(im2));

for (j = gdImageSY(im1) - 1; j >= 0; --j) {
for (i = gdImageSX(im1) - 1; i >= 0; --i) {
if (gdImageTrueColorPixel(im1, i, j) != gdImageTrueColorPixel(im2, i, j)) {
result++;
}
}
}

RETURN_LONG(result);
}

static double calc_pixel_distance(gdImagePtr im1, gdImagePtr im2, int x, int y)
{
int c1 = gdImageGetPixel(im1, x, y);
int c2 = gdImageGetPixel(im2, x, y);
# define SQR(a) ((a) * (a))
return sqrt(
SQR(gdImageRed(im1, c1) - gdImageRed(im2, c2)) +
SQR(gdImageGreen(im1, c1) - gdImageGreen(im2, c2)) +
SQR(gdImageBlue(im1, c1) - gdImageBlue(im2, c2)));
# undef SQR
}

static PHP_FUNCTION(calc_image_dissimilarity)
{
zval *IM1, *IM2;
gdImagePtr im1, im2;
int i, j;
double result = 0;

ZEND_PARSE_PARAMETERS_START(2, 2)
Z_PARAM_OBJECT_OF_CLASS(IM1, gd_image_ce)
Z_PARAM_OBJECT_OF_CLASS(IM2, gd_image_ce)
ZEND_PARSE_PARAMETERS_END();

im1 = php_gd_libgdimageptr_from_zval_p(IM1);
im2 = php_gd_libgdimageptr_from_zval_p(IM2);

ZEND_ASSERT(gdImageSX(im1) == gdImageSX(im2) && gdImageSY(im1) == gdImageSY(im2));

for (j = gdImageSY(im2) - 1; j >= 0; --j) {
for (i = gdImageSX(im1) - 1; i >= 0; --i) {
result += calc_pixel_distance(im1, im2, i, j);
}
}

RETURN_DOUBLE(result);
}
#endif

/*********************************************************
*
Expand Down
6 changes: 6 additions & 0 deletions ext/gd/gd.stub.php
Original file line number Diff line number Diff line change
Expand Up @@ -794,3 +794,9 @@ function imagesetinterpolation(GdImage $image, int $method = IMG_BILINEAR_FIXED)
* @refcount 1
*/
function imageresolution(GdImage $image, ?int $resolution_x = null, ?int $resolution_y = null): array|bool {}

#ifdef GD_TEST_HELPERS
function imagechangedpixels(GdImage $im1, GdImage $im2): int {}

function calc_image_dissimilarity(GdImage $im1, GdImage $im2): float {}
#endif
22 changes: 21 additions & 1 deletion ext/gd/gd_arginfo.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 18 additions & 10 deletions ext/gd/tests/func.inc
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,23 @@ function get_libxpm_version()
return $version;
}

if (!function_exists("imagechangedpixels")) {
function imagechangedpixels(GdImage $im1, GdImage $im2): int
{
$pixels_changed = 0;
for ($y = imagesy($im1) - 1; $y >= 0; --$y) {
for ($x = imagesx($im1) - 1; $x >= 0; --$x) {
$c1 = imagecolorat($im1, $x, $y);
$c2 = imagecolorat($im2, $x, $y);
if ($c1 != $c2) {
$pixels_changed++;
}
}
}
return $pixels_changed;
}
}

/**
* Tests that an in-memory image equals a PNG file.
*
Expand Down Expand Up @@ -106,16 +123,7 @@ function test_image_equals_image(GdImage $expected, GdImage $actual, bool $save_
}
return;
}
$pixels_changed = 0;
for ($y = 0; $y < $exp_y; $y++) {
for ($x = 0; $x < $exp_x; $x ++) {
$exp_c = imagecolorat($expected, $x, $y);
$act_c = imagecolorat($actual, $x, $y);
if ($exp_c != $act_c) {
$pixels_changed++;
}
}
}
$pixels_changed = imagechangedpixels($expected, $actual);
if (!$pixels_changed) {
echo "The images are equal.\n";
} else {
Expand Down
64 changes: 29 additions & 35 deletions ext/gd/tests/similarity.inc
Original file line number Diff line number Diff line change
Expand Up @@ -23,42 +23,36 @@ function get_rgb($color, &$red, &$green, &$blue)
$blue = $color & 0xFF;
}

/**
* Calculates the euclidean distance of two RGB values.
*
* @param int $color1
* @param int $color2
*
* @return int
*/
function calc_pixel_distance($color1, $color2)
{
get_rgb($color1, $red1, $green1, $blue1);
get_rgb($color2, $red2, $green2, $blue2);
return sqrt(
pow($red1 - $red2, 2) + pow($green1 - $green2, 2) + pow($blue1 - $blue2, 2)
);
}
if (!function_exists("calc_image_dissimilarity")) {
/**
* Calculates the euclidean distance of two RGB values.
*/
function calc_pixel_distance(int $color1, int $color2): float
{
get_rgb($color1, $red1, $green1, $blue1);
get_rgb($color2, $red2, $green2, $blue2);
return sqrt(
pow($red1 - $red2, 2) + pow($green1 - $green2, 2) + pow($blue1 - $blue2, 2)
);
}

/**
* Calculates dissimilarity of two images.
*
* @param resource $image1
* @param resource $image2
*
* @return int The dissimilarity. 0 means the images are identical. The higher
* the value, the more dissimilar are the images.
*/
function calc_image_dissimilarity($image1, $image2)
{
// assumes image1 and image2 have same width and height
$dissimilarity = 0;
for ($i = 0, $n = imagesx($image1); $i < $n; $i++) {
for ($j = 0, $m = imagesy($image1); $j < $m; $j++) {
$color1 = imagecolorat($image1, $i, $j);
$color2 = imagecolorat($image2, $i, $j);
$dissimilarity += calc_pixel_distance($color1, $color2);
/**
* Calculates dissimilarity of two images.
*
* 0 means the images are identical. The higher
* the value, the more dissimilar are the images.
*/
function calc_image_dissimilarity(GdImage $im1, GdImage $im2): float
{
// assumes image1 and image2 have same width and height
$dissimilarity = 0;
for ($j = imagesy($im1) - 1; $j >= 0; --$j) {
for ($i = imagesx($im1) - 1; $i >= 0; --$i) {
$color1 = imagecolorat($im1, $i, $j);
$color2 = imagecolorat($im2, $i, $j);
$dissimilarity += calc_pixel_distance($color1, $color2);
}
}
return $dissimilarity;
}
return $dissimilarity;
}
Loading