Skip to content

ImageMagick(Imagick)

ImageMagick 是一个功能强大的图像处理库,通过 PHP 的 Imagick 扩展提供接口。相比 GD,ImageMagick 支持更多图像格式、提供更丰富的图像操作(如锐化、模糊、色彩调整、蒙版、合成等),是专业图像处理的首选。

前置知识

阅读本节前,建议先了解:GD 图像处理

基础概念

安装

bash
# 安装 ImageMagick
sudo apt-get install imagemagick libmagickwand-dev

# PECL 安装 Imagick
pecl install imagick

# php.ini
extension=imagick.so

基本操作

读取和输出图像

php
<?php
declare(strict_types=1);

use Imagick;

// 从文件加载
$image = new Imagick('/path/to/image.jpg');

// 从字符串加载
$image = new Imagick();
$image->readImageBlob(file_get_contents('/path/to/image.jpg'));

// 创建新图像
$image = new Imagick();
$image->newImage(800, 600, new ImagickPixel('white'));

// 输出
header('Content-Type: image/jpeg');
echo $image->getImageBlob();

// 保存到文件
$image->writeImage('/path/to/output.jpg');

// 销毁
$image->clear();
$image->destroy();

格式转换

php
<?php
declare(strict_types=1);

use Imagick;

// JPG 转 PNG
$image = new Imagick('input.jpg');
$image->setImageFormat('png');
$image->writeImage('output.png');

// PNG 转 WebP
$image = new Imagick('input.png');
$image->setImageFormat('webp');
$image->setImageCompressionQuality(80);
$image->writeImage('output.webp');

// 支持的格式
$formats = Imagick::queryFormats();
echo "支持 " . count($formats) . " 种格式" . PHP_EOL;

图像处理

缩放和裁剪

php
<?php
declare(strict_types=1);

use Imagick;

$image = new Imagick('photo.jpg');

// 获取信息
$width = $image->getImageWidth();
$height = $image->getImageHeight();
echo "原始尺寸: {$width}x{$height}" . PHP_EOL;

// 等比缩放
$image->thumbnailImage(200, 200, true); // true = 保持比例

// 固定尺寸缩放
$image->scaleImage(200, 200); // 不保持比例

// 裁剪
$image->cropImage(200, 200, 50, 50); // 宽, 高, X, Y

// 旋转
$image->rotateImage(new ImagickPixel('none'), 90); // 逆时针90度

// 翻转
$image->flipImage();  // 垂直翻转
$image->flopImage();  // 水平翻转

滤镜和效果

php
<?php
declare(strict_types=1);

use Imagick;

$image = new Imagick('photo.jpg');

// 模糊
$image->blurImage(5, 3); // radius, sigma

// 锐化
$image->sharpenImage(2, 1);

// 灰度
$image->setImageColorspace(Imagick::COLORSPACE_GRAY);

// 黑白(二值化)
$image->thresholdImage(128);

// 反色
$image->negateImage(false);

// 浮雕效果
$image->embossImage(2, 1);

// 油画效果
$image->oilPaintImage(5);

// 添加边框
$image->borderImage(new ImagickPixel('#000000'), 2, 2); // 颜色, 宽, 高

// 添加阴影
$shadow = clone $image;
$shadow->setImageBackgroundColor(new ImagickPixel('black'));
$shadow->shadowImage(80, 5, 5, 5);

透明和通道

php
<?php
declare(strict_types=1);

use Imagick;

// 创建透明图像
$image = new Imagick();
$image->newImage(200, 200, new ImagickPixel('none'));
$image->setImageFormat('png');

// 设置透明度
$image->setImageOpacity(0.5); // 50% 透明

// 去除白色背景变透明
$image = new Imagick('image.png');
$image->setImageAlphaChannel(Imagick::ALPHACHANNEL_OPAQUE);
$image->evaluateImage(Imagick::EVALUATE_MULTIPLY, Imagick::COLOR_ALPHA, 0.5);

多帧操作(GIF 动画)

php
<?php
declare(strict_types=1);

use Imagick;

// 创建 GIF 动画
$gif = new Imagick();
$gif->setFormat('gif');

for ($i = 0; $i < 10; $i++) {
    $frame = new Imagick();
    $frame->newImage(200, 200, new ImagickPixel('#' . str_repeat(dechex($i * 25), 6)));

    // 添加文字
    $draw = new ImagickDraw();
    $draw->setFontSize(40);
    $draw->setFillColor(new ImagickPixel('white'));
    $frame->annotateImage($draw, 70, 110, 0, (string) $i);

    $frame->setImageDelay(100); // 100ms 每帧
    $gif->addImage($frame);
}

$gif->setImageIterations(0); // 无限循环
$gif->coalesceImages();

header('Content-Type: image/gif');
echo $gif->getImageBlob();

实战示例

批量图片处理

php
<?php
declare(strict_types=1);

use Imagick;

class ImageProcessor
{
    public function resizeDir(string $dir, int $maxWidth, int $maxHeight): void
    {
        $iterator = new DirectoryIterator($dir);
        foreach ($iterator as $file) {
            if ($file->isDot() || $file->isDir()) {
                continue;
            }

            $path = $file->getPathname();
            try {
                $image = new Imagick($path);
                $image->thumbnailImage($maxWidth, $maxHeight, true);
                $image->writeImage($path);
                $image->destroy();
                echo "处理: {$path}" . PHP_EOL;
            } catch (\Exception $e) {
                echo "跳过: {$path} - " . $e->getMessage() . PHP_EOL;
            }
        }
    }
}

注意事项

  • ImageMagick 内存占用较高,大图处理需设置足够的 memory_limit
  • 处理 SVG 时注意安全性(禁用非安全操作)
  • 使用 coalesceImages() 处理 GIF 动画确保帧间正确

下一节

继续学习:Exif 信息读取

参考链接