如何使用php调整图像大小并保持约束条件

3
我制作了两个GIF来解释我想做的事情。灰色边框是我要求的尺寸(700 * 525)。它们位于此问题的底部。
我希望所有大于给定宽度和高度的图像都缩小到边框(从中心开始),然后裁剪边缘。以下是我拼凑的一些代码来尝试实现这一点:
if ($heightofimage => 700 && $widthofimage => 525){
    if ($heightofimage > $widthofimage){
    
        $widthofimage = 525;
        $heightofimage = //scaled height.
        
        //crop height to 700.
    
    }
    
    if ($heightofimage < $widthofimage){
    
        $widthofimage = //scaled width.
        $heightofimage = 700;
        
        //crop width to 525.
    
    }
}else{
    echo "image too small";
}

这里有一些GIF图,可以直观地解释我想要实现的内容: GIF 1: 图像比例在x方向上过大。

enter image description here

GIF 2:这里的图像比例在y方向上过大。

enter image description here


@timclutton的图像质量比较

我使用了您的方法(点击此处使用PHP进行自己的测试),然后将其与原始照片进行了比较,如您所见有很大的差异:

您的PHP方法:

enter image description here
(来源:tragicclothing.co.uk)

实际文件:

在此输入图像描述
(来源:mujjo.com)



2
你可能会对CSS background-size:cover感兴趣。这里有一个例子。请注意,它的浏览器兼容性有些受限。(顺便说一句,动态GIF的使用很不错。) - showdev
请在 http://jsfiddle.net 上制作一个可工作的示例,展示你目前所拥有的内容。 - Jared Farrish
我喜欢你的 GIF!这是一种非常好的表达方式,笑死我了!XD! - Federico J.
4个回答

9
下面的代码应该能够实现你想要的功能。我没有进行过广泛的测试,但它似乎可以在我制作的几个测试图像上工作。我有一个疑虑,就是我的数学可能有误,但现在太晚了,我看不出任何明显的问题。
编辑:这个疑虑足够让我再次检查,并找到了错误,即裁剪不在图像中心。代码已被替换为可工作版本。
简而言之:把它当作起点,而不是生产就绪的代码!
<?php

// set image size constraints.
$target_w = 525;
$target_h = 700;

// get image.
$in = imagecreatefrompng('<path to your>.png');

// get image dimensions.
$w = imagesx($in);
$h = imagesy($in);

if ($w >= $target_w && $h >= $target_h) {
    // get scales.
    $x_scale = ($w / $target_w);
    $y_scale = ($h / $target_h);

    // create new image.
    $out = imagecreatetruecolor($target_w, $target_h);

    $new_w = $target_w;
    $new_h = $target_h;
    $src_x = 0;
    $src_y = 0;

    // compare scales to ensure we crop whichever is smaller: top/bottom or
    // left/right.
    if ($x_scale > $y_scale) {
        $new_w = $w / $y_scale;

        // see description of $src_y, below.
        $src_x = (($new_w - $target_w) / 2) * $y_scale;
    } else {
        $new_h = $h / $x_scale;

        // a bit tricky. crop is done by specifying coordinates to copy from in
        // source image. so calculate how much to remove from new image and
        // then scale that up to original. result is out by ~1px but good enough.
        $src_y = (($new_h - $target_h) / 2) * $x_scale;
    }

    // given the right inputs, this takes care of crop and resize and gives
    // back the new image. note that imagecopyresized() is possibly quicker, but
    // imagecopyresampled() gives better quality.
    imagecopyresampled($out, $in, 0, 0, $src_x, $src_y, $new_w, $new_h, $w, $h);

    // output to browser.
    header('Content-Type: image/png');
    imagepng($out);
    exit;

} else {
    echo 'image too small';
}

?>

这对我来说可行,但如果图片不是png格式,你可以使用: $ext = strtolower(substr(strrchr($file_name,'.'), 1)); if($ext == 'png') $in = imagecreatefrompng($source); else $in = imagecreatefromjpeg($source);如果($ext == 'png') imagepng($out); else imagejpeg($out); - Nam Nguyen
这种方法会大幅降低图像的质量!请参考我问题中的更新... - maxisme
也许只是我的老眼昏花了,但我看不出你发布的这两张图片有太大的区别(对于大多数互联网用户/设备来说,这并不足以引起担忧)。当然,由于PS和GD使用不同的方法来完成此操作,结果肯定会有所不同。如果质量是您最重要的目标,那么请使用PS方法。 - timclutton
@timclutton请查看更新,是否有其他方法可以创建更高质量的图像PHP?谢谢。 - maxisme
imagepng() 的第三个参数是压缩设置,范围从0(无)到9。默认值(在我的代码中使用)为6。您可以尝试更改它。另一个选择是尝试使用ImageMagick而不是GD。但是,如果您裁剪和调整源图像,则会出现质量损失。您的结果图像用途是什么?对于我来说,结果在网页上显示得很好。如果质量是您最关心的问题,请勿裁剪和调整大小。 - timclutton

0
使用 Imagick
define('PHOTO_WIDTH_THUMB', 700);
define('PHOTO_HEIGHT_THUMB', 525);

$image = new Imagick();
$image->readImage($file_source);
$width = $image->getImageWidth();
$height = $image->getImageHeight();

if($width > $height){
  $image->thumbnailImage(0, PHOTO_HEIGHT_THUMB);
}else{
  $image->thumbnailImage(PHOTO_WIDTH_THUMB, 0);
}

$thumb_width = $image->getImageWidth();
$thumb_height = $image->getImageHeight();
$x = ($thumb_width - PHOTO_WIDTH_THUMB)/2;
$y = ($thumb_height - PHOTO_HEIGHT_THUMB)/2;
$image->cropImage(PHOTO_THUMB_WIDTH, PHOTO_THUMB_HEIGHT, $x, $y);
$image->writeImage($thumb_destination);

$image->clear();
$image->destroy();
unlink($file_source);

我建议您删除最后一行代码 (unlink($file_source);),以防有人没有仔细阅读就使用该代码,结果可能会丢失他们想要保留的文件。 - timclutton

0

我使用了GD库来完成调整大小。基本上我所做的是,计算图像尺寸,然后从中心调整图像尺寸为700x525。

<?php
/*
 * PHP GD
 * resize an image using GD library
 */

//the image has 700X525 px ie 4:3 ratio
$src = 'demo_files/bobo.jpg';

// Get new sizes
list($width, $height) = getimagesize($src);

$x = 0;
$y = 0;
if($width < $height){
    $newwidth = $width;
    $newheight = 3/4 * $width;
    $x = 0;
    $y = $height/2 - $newheight/2;
}else{
    $newheight = $height;
    $newwidth = 4/3 * $height;
    $x=$width/2 - $newwidth/2;
    $y=0;

}

$targ_w = 700; //width of the image to be resized to
$targ_h = 525; ////height of the image to be resized to
$jpeg_quality = 90;

$img_r = imagecreatefromjpeg($src);
$dst_r = ImageCreateTrueColor( $targ_w, $targ_h );

imagecopyresampled($dst_r,$img_r,0,0,$x,$y,$targ_w,$targ_h,$newwidth,$newheight);

header('Content-type: image/jpeg');
imagejpeg($dst_r,null,$jpeg_quality);

exit;

?>

0
我使用了http://phpthumb.sourceforge.net来实现一个美观的解决方案,同时还带有透明的弧边。
这是一种替代方案,可能适合某些需要进行少量配置的人。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接