Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Resize image with background fill for vertical and horizontal images

I am trying to create an image gallery. I want to try this time with PHP Image Magick.

When a file is uploaded I want it to be resized to 1024x724. If the image is vertical (width < height ) I want it to be fitted in the center of the image and transparent background ( or white if not possible ) at both sides where should be blank, so the image can be always 1024x724 and the aspect radio to be kept.

Same applies if the image is horizontal ( width > height ).

Here is my code so far:

$img = new Imagick($targetFile);
$img->scaleImage(1024,724);
$img->setGravity(imagick::GRAVITY_CENTER);
$img->setImageBackgroundColor('white');
$img->extentImage(1024,724,0,0);

$img->writeImage($targetFile);

$img = new Imagick($targetFile);
$img->scaleImage(150,150);
$img->setGravity(imagick::GRAVITY_CENTER);
$img->setImageBackgroundColor('white');
$img->extentImage(150,150,0,0);

$img->writeImage($targetThumb);
like image 642
Izopi4a Avatar asked Mar 02 '13 15:03

Izopi4a


People also ask

How do I resize an image using CSS without losing the aspect ratio?

The Simple Solution Using CSSBy setting the width property to 100%, you are telling the image to take up all the horizontal space that is available. With the height property set to auto, your image's height changes proportionally with the width to ensure the aspect ratio is maintained.

How do you resize a photo proportionally?

Image resizing with the pointer toolBy clicking and dragging on these handles, the object is resized by moving the edge or corner clicked on to adjust the width and/or height of the selected object. If the Shift key is held down whilst moving the handle, then the proportions of the object will be preserved.

How do I resize an image without stretching CSS?

How to fit image without stretching and maintain aspect ratio? Answer: If you want to use the image as a CSS background, there is an elegant solution. Simply use cover or contain in the background-size CSS3 property. contain will give you a scaled-down image.

How do I resize an image using CSS?

We can resize the image by specifying the width and height of an image. A common solution is to use the max-width: 100%; and height: auto; so that large images do not exceed the width of their container. The max-width and max-height properties of CSS works better, but they are not supported in many browsers.


1 Answers

If I am understanding what you want correctly, you are already part way there. Right now if you try to use a transparent PNG (source and destination), instead of a jpeg, it'll flatten the image and make the background solid white, and you do not want this correct?

What you'll need to do is determine if the image has, or might have, transparency and then set the background color to None. -extent flattens images, so to preserve the transparency the background will need to be None in those cases. (And, as mentioned, you will of course need to use png or gif output rather than jpg as jpeg can't handle transparency.) Normally I would do simple extension checking as it's good enough most of the time, but there are more detailed checks.

$background = preg_match('/\.gif$|\.png$/', $thumbnailFilename) == 1 ? 'None' : 'white';
$edge = shell_exec("convert $imgFile -resize 1024x724 -background $background -gravity center -extent 1024x724 -quality 90 $thumbnailFilename");

I check the output thumbnail here because if you are outputting to a jpeg, regardless of the source, it's going to be stripped of transparency. With this, if you provide $imgFile as test-transparent1.png and $thumbnailFilename as test-transparent1.sized.png, test-transparent1.sized.png should come out being sized to fit 1024x724 and padded with transparent pixels so the original image is centered.

==Edit for ImageMagick PHP class:==

First, in order to do a proportional scale, you'll need to set the bestfit parameter of scaleImage to true. Additionally, it appears that extentImage doesn't use the gravity option at all when you use the API, so we have to use negative X or Y offsets to properly center the image on the new canvas. Here's what my test script looked like once I got it working:

<?php
$targetFile = 'mizu.png';
$targetThumb = 'mizu.thumb.png';

$background = preg_match('/\.gif$|\.png$/', $targetThumb) == 1 ? 'None' : 'white';

$img = new Imagick($targetFile);

$img->scaleImage(150,150,true);
$img->setImageBackgroundColor($background);
$w = $img->getImageWidth();
$h = $img->getImageHeight();
$img->extentImage(150,150,($w-150)/2,($h-150)/2);
$img->writeImage($targetThumb);

== Update per comments: ==

For those who come to this answer and are using imagemagick after 6.5.7-8, this answer needs to be adjusted so that the extentImage x and y values are negative. you can see the caution note at php.net/manual/en/imagick.extentimage.php - courtesy of Jeff Richards

like image 65
EPB Avatar answered Nov 14 '22 11:11

EPB