3

I have a script that takes an image and when resampled centers the short dimension (width or height) on a square coloured background. This works fine for images with a longer WIDTH but for some reason any image with a longer HEIGHT the result is a split background fill - the correct colour on the left but the default black on the right. If I play with the x-axis offset the background fill only extends to the right as far as the image placement.

The calculated values are as expected for the vertical images so I cannot figure out what is happening here. Note that 'imagecopy()' produces the exact same behaviour.

  • original image is 155 x 400px
  • adjusted source dimensions for square aspect ratio = 400 x 400px
  • resulting thumbnail to be 250 x 250px

Here is the code with static values for one example:

$thumb = imagecreatetruecolor(250, 250);

imagecopyresampled($thumb, $source, 77, 0, 0, 0, 250, 250, 400, 400);

$blue = imagecolorallocate($thumb, 0xDE, 0xE6, 0xF9);
imagefill($thumb, 0, 0, $blue);

Using the same image rotated 90 degrees (400 x 155 px) so it is longer horizontally DOES apply the full background fill:

imagecopyresampled($thumb, $source, 0, 77, 0, 0, 250, 250, 400, 400);

For the vertical image, my coordinate values (77, 0) place the image on the imagecreatetruecolor() canvas centered exactly where I want it but changing any of the other imagecopyresampled() values stretch or squeeze the resampled image or crop it.

Am I overlooking something simple? View the screenshots here: https://i.stack.imgur.com/5CxHU.jpg (vertical issue) and https://i.stack.imgur.com/wvhzP.jpg (OK horizontally)

cartimus
  • 41
  • 3
  • 0,77 and 250,250 means "at horizontal 0 and vertical 77, start drawing an image that'll be 250x250". e.g. 0,77 -> 250,327, so you're drawing off the bottom of your target image, since you "wasted" 77 pixels at the top of the picture. – Marc B May 19 '15 at 19:07
  • I edited above to clarify that a horizontal image (400 x 155 px) works (0,77), it is the vertical image (155 x 400 px) that causes the imagefill() issue. I also included links to the screenshots. – cartimus May 21 '15 at 13:16
  • This applies the background fill correctly: $thumb = imagecreatetruecolor(250, 327); ...but leaves me with an excess 77 pixels on the bottom that I would need to then crop off with imagecopy() or imagecrop()...just wish I could figure out how to get it in one step. – cartimus May 21 '15 at 13:17

1 Answers1

0

This vertical issue must have something to do with PHP's resampling/imagefill algorithm (?) but here is a workaround that now works for centering all of my vertical images within my square canvas:

1) You need to first pad your image placeholder so the background fill will extend to the right edge in the resampled image by extending the thumbnail height with your x-axis offset (sounds odd but it works)...we will trim this off later:

$thadj_height = $th_height + $th_x;
$thumb = imagecreatetruecolor($th_width, $thadj_height);

2) Resample as usual with the background fill (note that the fill is applied AFTER the resampling statement, odd but just works that way)...remember that $thumb has more height than what $th_width, $th_height will occupy:

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

3) Temporarily save the image output so a new function can be applied to it next - set quality to lossless since we'll be reusing it:

imagejpeg($thumb, "resampled/output_temp.jpg", 100);
imagedestroy($thumb);

4) Retrieve the temporary file and grab the new dimensions (overwrite the previous variables):

$file = "resampled/output_temp.jpg";
$image = file_get_contents($file);
$source = imagecreatefromstring($image);
list($src_width, $src_height) = getimagesize($file);

5) Create a new image placeholder, square as originally intended in my case:

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

6) Now copy the temporary padded thumbnail into the square placeholder which will result in cropping off the padding:

imagecopy($thumb, $source, 0, 0, 0, 0, $src_width, $src_height);

header('Content-Type: image/jpeg');
echo imagejpeg($thumb);
imagedestroy($thumb);

Again, none of this is necessary for centering my horizontal images on a square canvas but this is a workaround that will work to eliminate the split fill background.

cartimus
  • 41
  • 3