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

Resize Artifact #99

Open
imazen-bot opened this Issue Feb 5, 2015 · 9 comments

Comments

Projects
None yet
6 participants
@imazen-bot
Copy link

imazen-bot commented Feb 5, 2015

Hi Pierre,

Following your recommandation on the mailing list I open a new issue : If I resize a picture to a size which is not a multiple of the original size I have artifacts on the white background.

I just had a test on php5.53 and the bug is still here :

Here is the code I used to test (test.jpg is a 1000x1000 jpeg)

#!php
<?php
$filename = 'test.jpg';
$percent = $_GET["scale"] ?  $_GET["scale"] : 1;

// Content type
header('Content-Type: image/jpeg');

// Get new dimensions
list($width, $height) = getimagesize($filename);
$new_width = $width * $percent;
$new_height = $height * $percent;

// Resample
$image_p = imagecreatetruecolor($new_width, $new_height);
$image = imagecreatefromjpeg($filename);
imagecopyresampled($image_p, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);

// Output
imagejpeg($image_p, null, 100);

You can find the resulting jpg in attachment (If you can't see the artifact just add contrast in photoshop)


@imazen-bot

This comment has been minimized.

Copy link

imazen-bot commented Feb 5, 2015

A better testcase:

#!php

<?php

// Request input parameters
$percent = isset($_GET["scale"]) ?  floatval($_GET["scale"]) : 1;

// Build original image
$width = $height = 1000;
$image = imagecreatetruecolor($width, $height);
$white = imagecolorallocate($image, 255, 255, 255);
imagefill($image, 0, 0, $white);

// Get new dimensions
$new_width = $width * $percent;
$new_height = $height * $percent;

// Resample
$image_p = imagecreatetruecolor($new_width, $new_height);
imagecopyresampled($image_p, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);

// Output
header('Content-Type: image/png');
imagepng($image_p, null);


Originally posted by ChALkeR (ChALkeR) on Jan 02 2014 via Bitbucket

@vapier vapier added the bug label Apr 22, 2015

@sotebuy

This comment has been minimized.

Copy link

sotebuy commented Nov 3, 2015

I can confirm the same bug on PHP 5.6.10 is somebody addressing the issue?

@vapier vapier added the help wanted label Nov 3, 2015

@KaipiYann

This comment has been minimized.

Copy link

KaipiYann commented Feb 9, 2016

Problem can be solved using imagescale :
$image_p = imagescale($image, $new_width, $new_height, IMG_NEAREST_NEIGHBOUR);

Just tested and it works.

@cmb69

This comment has been minimized.

Copy link
Contributor

cmb69 commented Jun 8, 2016

You can find the resulting jpg in attachment (If you can't see the artifact just add contrast in photoshop)

If I maximally decrease brightness and increase contrast, I can see artifacts, but these may be usual JPEG compression artifacts (note that JPEG quality 100 doesn't mean lossless compression). I suggest that you check with a PNG image (which is lossless).

I can confirm the same bug on PHP 5.6.10 is somebody addressing the issue?

I would need a good sample (original and resampled plus code) to reproduce the issue.

$image_p = imagescale($image, $new_width, $new_height, IMG_NEAREST_NEIGHBOUR);

Hm, IMG_NEAREST_NEIGHBOUR is not everybody's favorite. If I'm not mistaken, that is the same as imagecopyresized().

@pierrejoye

This comment has been minimized.

Copy link
Contributor

pierrejoye commented Jun 8, 2016

Also the artifacts may be gone too with libgd from.here. I change the sampling for q>=90 so almost no artefacts should appear.

@pierrejoye

This comment has been minimized.

Copy link
Contributor

pierrejoye commented Jun 8, 2016

2.2 or master branches. This charge will be in 2.2.2 or next 5.6/7.0/7.1

@pierrejoye

This comment has been minimized.

Copy link
Contributor

pierrejoye commented Jun 11, 2016

@cmb69 for the record here, imagecopyresanpled uses a kind of bicubic interpolation, not nearest.

@cmb69

This comment has been minimized.

Copy link
Contributor

cmb69 commented Jun 11, 2016

imagecopyresanpled uses a kind of bicubic interpolation, not nearest.

Yes, I know. :) Therefore I'm preferring imagecopyresampled() over imagecopyresized() (even though the latter is a bit faster).

@cmb69

This comment has been minimized.

Copy link
Contributor

cmb69 commented Aug 21, 2016

Well, actually this is the same issue that has been reported as https://bugs.php.net/bug.php?id=53580, including a rather terse analysis. The culprit appears that we cast float/double to int.

Reproduce script:

<?php

$src = imagecreatetruecolor(4, 4);
$white = imagecolorallocate($src, 255, 255, 255);
imagefilledrectangle($src, 0,0, 3,3, $white);

for ($i = 0; $i < 4; $i++) {
    for ($j = 0; $j < 4; $j++) {
        assertColorAt($src, $i, $j, $white);
    }
}

$dst = imagecreatetruecolor(7, 7);

imagecopyresampled($dst, $src, 0,0, 0,0, 7,7, 4,4);

for ($i = 0; $i < 7; $i++) {
    for ($j = 0; $j < 7; $j++) {
        assertColorAt($dst, $i, $j, $white);
    }
}


function assertColorAt($im, $x, $y, $exp_color) {
    $act_color = imagecolorat($im, $x, $y);
    if ($act_color !== $exp_color) {
        printf("color of %2d,%2d is %x, expected %x\n", $x, $y, $act_color, $exp_color);
    }
}

The result is likely system dependent, but for me it's (current PHP master with bundled GD):

color of  1, 5 is fefefe, expected ffffff
color of  5, 1 is fefefe, expected ffffff
color of  5, 5 is fefefe, expected ffffff

And (current PHP master with current GD master):

color of  0, 3 is fefefe, expected ffffff
color of  3, 0 is fefefe, expected ffffff

gdImageScale() has similar issues depending on the algorithm. For instance, GD_BILINEAR_FIXED works as expected, while GD_BICUBIC and GD_BICUBIC_FIXED even produce several fcfcfc pixels.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment