使用Imagick和PHP进行居中裁剪

12

我想使用 Imagick PHP API(而不是 Imagick 的命令行版本)来进行居中裁剪图像。

本质上,我想要使用 API 实现与命令行相同的功能。以下是使用命令行的示例: http://www.imagemagick.org/Usage/crop/#crop_gravity

以下是我的尝试(但无效)。它总是裁剪源图像的左上角:

        $this->imagickObj->setGravity(\Imagick::GRAVITY_CENTER);
        $this->imagickObj->cropImage(300,250,0,0);
        $this->imagickObj->setImagePage(0, 0, 0, 0);

为什么setGravity方法在裁剪之前没有应用于图像上?http://www.php.net/manual/en/function.imagick-setgravity.php中提到它应该应用于对象上(在这种情况下是单个图像)...

4个回答

17

对于之前提出问题的人来说,现在已经太晚了,但对于未来的访问者,正确的解决方案是:

bool Imagick::cropThumbnailImage ( int $width , int $height )

很抱歉回复晚了,但我30分钟之前也卡在这里,第一个谷歌搜索结果将我带到了这里。希望其他人不会遇到同样的问题。


2
这是否总是居中裁剪?如果我想改变重力,怎么办? - rynop
1
是的,它总是以中心重力裁剪。实际上,它首先缩放图像以匹配高度或宽度,然后从中心裁剪以创建任何图像的缩略图。这是Facebook、Twitter、Google和许多其他网站用来创建缩略图的相同逻辑。如果您需要更改重心,请使用在http://php.net/manual/zh/imagick.cropimage.php中定义的`bool Imagick::cropImage ( int $width , int $height , int $x , int $y )`。 - Kapil Sharma

4

你如何定义这些计算? - j0k

0
Imagemagick 对象的 cropImage() 方法的第三个和第四个参数定义了裁剪的左上角。您可以尝试将它们作为 null 传递(并使用 setGravity() 方法),或者您可能需要计算裁剪应该发生的位置,并将这些数字放入 cropImage() 方法中(不要使用 setGravity())。就我所知,我已经在使用 PHP 编写 Imagemagick 的大量代码,由于 Imagemagick 扩展的可怕文档,我不得不制作很多好的命令行调用。

谢谢。null,null不起作用。 如果可能的话,我更愿意利用内置功能来完成数学计算。我想避免使用CLI的原因有很多,其中之一是性能问题(我正在编写一个图像处理服务,将被广泛使用)。 - rynop
我编写的主要服务使用CLI处理每天数千张图像,运行在一台安装有4GB RAM的Intel Core i5 760 Linux服务器上,同时还提供几个网站服务,运行非常稳定。 - WWW
谢谢。我决定只做数学计算,因为这只需要几分钟时间。我会把这个问题保持开放状态几天,看看是否有人知道如何使用内置的重力功能。 - rynop

0
我创建了一个组件来裁剪和调整图像大小,以下是代码(yii2)。
该组件使用 imagine/imagine 扩展,请先安装它。
<?php
namespace common\components;

use Imagine\Gd\Imagine;
use Imagine\Image\Box;
use Imagine\Image\ImageInterface;
use Imagine\Image\Point;
use Imagine\Imagick\Image;

class ResizeComponent
{
    /**
     * Resize image
     * @param  string   $source         source image path
     * @param  string   $destination    destination image path
     * @param  int      $width
     * @param  int      $height
     * @param  int      $quality        Jpeg sampling quality (0-100, 80 is best for seo)
     * @return boolean                  is picture cropped
     */
    public static function resizeImage($source, $destination, $width, $height, $quality = 80)
    {
        if (file_exists($source) && is_file($source)) {
            $imagine   = new Imagine();
            $size      = new Box($width, $height);
            $mode      = ImageInterface::THUMBNAIL_INSET;
            $resizeimg = $imagine->open($source)->thumbnail($size, $mode);
            $sizeR     = $resizeimg->getSize();
            $widthR    = $sizeR->getWidth();
            $heightR   = $sizeR->getHeight();
            $preserve  = $imagine->create($size);
            $startX    = $startY    = 0;
            if ($widthR < $width) {
                $startX = ($width - $widthR) / 2;
            }
            if ($heightR < $height) {
                $startY = ($height - $heightR) / 2;
            }
            $preserve->paste($resizeimg, new Point($startX, $startY))
                ->save($destination, array('jpeg_quality' => $quality));
            return true;
        } else {
            return false;
        }
    }

    /**
     * Crop image
     * @param  string   $source         source image path
     * @param  string   $destination    destination image path
     * @param  int      $width
     * @param  int      $height
     * @param  int      $quality        Jpeg sampling quality (0-100, 80 is best for seo)
     * @return boolean                  is picture cropped
     */
    public static function cropImage($source, $destination, $width, $height, $quality = 80)
    {
        if (file_exists($source) && is_file($source)) {
            $imagine = new Imagine();
            $size    = new Box($width, $height);
            $mode    = ImageInterface::THUMBNAIL_OUTBOUND;
            $image   = $imagine->open($source)->thumbnail($size, $mode);
            $image->thumbnail($size, $mode)->save($destination, array('jpeg_quality' => $quality));
            return true;
        } else {
            return false;
        }
    }
}

裁剪和调整大小的区别是:

  • 裁剪无法显示所有图像,因此边框将被裁剪(最适合非信息缩略图)
  • 调整大小显示完整图像,但边框将填充静态颜色(或透明度,如果需要)(最适合需要显示所有图像的情况,例如商店目录)

最佳实践是将此组件静态使用,作为服务定位器。


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