Domanda

I don't use Imagemagick very often, which is why I don't know how to solve this problem. I also don't know how to phrase the question other than: How do I get the image to be cropped like the CSS property: background-size: contain; I haven't been able to find an answer, likely due to my phrasing.

I need the image to be 200px, and "resized/cropped" so that it is not stretched, but contained by the width or height (dependent on the orientation of the image width > height = contain by width)

What I have so far:

$im = new Imagick($path);

/* Resizing Operations */

$gm = $im->getImageGeometry();
$w = $gm['width'];
$h = $gm['height'];

if($h < $w) {
    $nh = 200;
    $nw = (200 / $h) * $w;
} else {
    $nw = 200;
    $nh = (200 / $w) * $h;
}

$im->resizeImage($nw, $nh, Imagick::FILTER_LANCZOS, true);
$im->cropThumbnailImage(200,200);

/* End Resizing Operations */

Which produces an image with the center chopped out.

Here's a visual example

We have this logo:

Original Logo


And then we want it to be constrained to 200px wide and 200px high, contained:

resized

Essentially like setting the canvas height, while not adjusting the image height.

È stato utile?

Soluzione

Came up with this algorithm based on the extent method of ImageMagick, which achieves the same result as CSS's background-size: contain;

You can set the 200 value in the resizeImage function to get your end product. Works beautifully!

$im = new Imagick($path);

/* Resizing Operations */
$gm = $im->getImageGeometry();
$w = $gm['width'];
$h = $gm['height'];

if($h < $w) {
    $sr = $w;
    $horz = TRUE;
} else if($h > $w) {
    $sr = $h;
    $horz = FALSE;
} else {
    $square = TRUE;
}

if(!$square && $horz) {
    $srs = $sr / 2;
    $extent_amt = $srs - ($h / 2);
    $im->extentImage($sr, $sr, 0, 0 - $extent_amt);
} else if(!$square && !$horz) {
    $srs = $sr / 2;
    $extent_amt = $srs - ($w / 2);
    $im->extentImage($sr, $sr, 0 - $extent_amt, 0);
}

$im->resizeImage(200, 200, Imagick::FILTER_LANCZOS, true);

/* End Resizing Operations */

$im->writeImage($path);

/* Clean up time */
$im->clear();
$im->destroy();

Altri suggerimenti

it seems like this would work for you, in that it operates in the same way that the background-size:contain; works in CSS

$path = __DIR__ . '/img.jpg';
$im = new Imagick($path);

$gm = $im->getImageGeometry();
$w = $gm['width'];
$h = $gm['height'];

if ($w >= $h) {
    $target_height = 0;
    $target_width = 200;
} elseif ($h > $w) {
    $target_height = 200;
    $target_width = 0;
}

$im->resizeImage($target_width, $target_height, Imagick::FILTER_LANCZOS, true);

$im->writeImage($path);
$im->clear();
$im->destroy();
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top