简体   繁体   中英

PHP imagecopyresampled() produces image border on one side

I have a resampling script that centers resampled images on a square canvas. For horizontally-oriented images that are centered vertically on a white background a line is added along the BOTTOM edge of the resampled image. For vertically-oriented images that are centered horizontally the line appears on the RIGHT edge of the resampled image.

$thumb = imagecreatetruecolor($th_width, $th_height);

imagecopyresampled($thumb, $source, $th_x, $th_y, 0, 0, $th_width, $th_height, $src_width, $src_height);

$bgcolor = imagecolorallocate($thumb, 255, 255, 255);
imagefill($thumb, 0, 0, $bgcolor);

The line is there regardless of background fill, it just shows up most on white.重采样边框问题

What causes this? No amount of adjusting parameter values will get rid of it (they just offset the resampled image on the background or distort it).

I am providing my own workaround for this issue. It appears the image border artifact is a COMBINATION result of 'imagecopyresampled()' AND centering offsets. If I just resample the image as-is THEN center and fill the image, the border is avoided. Here is the workaround:

1) RESAMPLE your image as-is (same aspect ratio) then SAVE to retain changes:

$thumb = imagecreatetruecolor($res_width, $res_height);

imagecopyresampled($thumb, $source, 0, 0, 0, 0, $res_width, $res_height, $src_width, $src_height);

// SAVE new image - set quality to lossless since reusing it:
imagejpeg($thumb, "resampled/output_temp.jpg", 100);

2) Retrieve the temporary image:

$file = "resampled/output_temp.jpg";
$image = file_get_contents($file);
$source = imagecreatefromstring($image);

// Get the RESAMPLED image dimensions
list($src_width, $src_height) = getimagesize($file);

3) NOW apply CENTERING and FILL:

$thumb = imagecreatetruecolor($th_width, $th_height);

// COPY the image
imagecopy($thumb, $source, $th_x, $th_y, 0, 0, $src_width, $src_height);

$bgcolor = imagecolorallocate($thumb, 255, 255, 255);

// Replace default black background - this must be placed AFTER imagecopy()
imagefill($thumb, 0, 0, $bgcolor);

// Save image (uses default quality setting 75)
imagejpeg($thumb, "resampled/" . $newfile);

// Optionally free up memory:
imagedestroy($thumb);

The result is a clean image. For correcting incomplete imagefill() on the background when centering vertically-oriented images see this post: imagecopyresampled() results in split color background imagefill()

This is likely happening because sometimes the result of resampling is a repeating decimal and it needs to make up for the extra bit (eg 1000px / 3 leaves.333... which cannot be represented by a pixel).

If you're ok with sometimes losing one pixel on one of the dimensions you could just subtract one pixel from each of your $thx_x and $thx_y . ie:

imagecopyresampled($thumb, $source, $th_x - 1, $th_y - 1, 0, 0, $th_width, $th_height, $src_width, $src_height);

Or to make it cleaner, do it wherever you define $th_x and $th_y .

And if you're not ok with sometimes losing that pixel, you could wrap it in an if statement that checks if the result is a repeating decimal and only subtract the pixel when it is.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM