PHP项目如何压缩图片资源?

wen PHP项目 8

本文目录导读:

PHP项目如何压缩图片资源?

  1. 方案一:使用 GD 库(PHP 内置,无需额外安装)
  2. 方案二:使用 Imagick 扩展(推荐,功能强大)
  3. 方案三:使用第三方库(如 Intervention Image)
  4. 方案四:调用外部 API / 云服务(大规模、高性能)
  5. 总结建议

在 PHP 项目中压缩图片资源,通常有几种主流的方案,从使用 PHP 扩展或库集成外部服务

以下是几种最常用、最有效的方法,按推荐程度排序:

使用 GD 库(PHP 内置,无需额外安装)

优点: PHP 标配,大多数环境都支持,简单快速。 缺点: 压缩率一般,不支持 WebP(旧版本),功能相对基础。

核心原理: 读取图片 -> 重新采样/调整尺寸 -> 设置输出质量 -> 保存。

<?php
function compressImageGD($sourcePath, $destinationPath, $quality = 75) {
    // 1. 获取图片信息
    $info = getimagesize($sourcePath);
    $mime = $info['mime'];
    // 2. 根据类型创建图像资源
    switch ($mime) {
        case 'image/jpeg':
            $image = imagecreatefromjpeg($sourcePath);
            break;
        case 'image/png':
            $image = imagecreatefrompng($sourcePath);
            // PNG 的 quality 参数在 GD 中实际上是压缩级别 (0-9),需要转换
            // quality 0 (无压缩) -> 9 (最大压缩);习惯上我们想用高quality保持画质,但这里相反
            // 如果不改变尺寸,可以使用 imagepng, quality 参数 0-9
            // 更推荐用 imagejpeg 转一遍(会损失透明度,但压缩率高)
            imagepng($image, $destinationPath, 9); // 9 是最大压缩
            imagedestroy($image);
            return true;
        case 'image/gif':
            $image = imagecreatefromgif($sourcePath);
            imagegif($image, $destinationPath);
            imagedestroy($image);
            return true;
        case 'image/webp':
            // 高版本 PHP 支持
            $image = imagecreatefromwebp($sourcePath);
            imagewebp($image, $destinationPath, $quality);
            imagedestroy($image);
            return true;
        default:
            return false;
    }
    // 3. 调整尺寸(可选,最有效的压缩方式)
    // $newWidth = imagesx($image) * 0.8; // 缩小到80%
    // $newHeight = imagesy($image) * 0.8;
    // $newImage = imagecreatetruecolor($newWidth, $newHeight);
    // imagecopyresampled($newImage, $image, 0, 0, 0, 0, $newWidth, $newHeight, imagesx($image), imagesy($image));
    // $image = $newImage;
    // 4. 输出并设置质量 (JPEG/WebP)
    if ($mime === 'image/jpeg') {
        imagejpeg($image, $destinationPath, $quality); // quality 0-100
    } elseif ($mime === 'image/webp') {
        imagewebp($image, $destinationPath, $quality);
    }
    // 5. 释放内存
    imagedestroy($image);
    return true;
}
// 使用示例
compressImageGD('origin.jpg', 'compressed.jpg', 60);
?>

注意

  • $quality 值越低,文件越小,画质越差,一般 60-80 是个不错的平衡点。
  • PNG 压缩在 GD 里效果一般,且会损失透明度,如果需要保留透明 PNG,建议用方案二。

使用 Imagick 扩展(推荐,功能强大)

优点: 支持格式多(WebP、HEIC、AVIF),压缩算法更优,支持高级参数(如 strip EXIF、渐进式)。 缺点: 需要服务器安装 imagick 扩展。

核心原理: 利用 ImageMagick 库进行精细化处理。

<?php
function compressImageImagick($sourcePath, $destinationPath, $quality = 75) {
    $imagick = new \Imagick(realpath($sourcePath));
    // 1. 设定压缩质量 (0-100)
    $imagick->setImageCompressionQuality($quality);
    // 2. 移除所有 EXIF 数据(相机信息、GPS等),可减少大量体积
    $imagick->stripImage();
    // 3. 优化图片(针对 JPEG/PNG 的额外无损压缩)
    // $imagick->setInterlaceScheme(Imagick::INTERLACE_PLANE); // 渐进式 JPEG
    // 4. 调整尺寸(可选)
    // $imagick->resizeImage(800, 0, Imagick::FILTER_LANCZOS, 1); // 宽度800,高度自适应
    // 5. 如果原图是 PNG,可以转成 JPEG(体积会小很多,但会损失透明背景)
    // $imagick->setImageFormat('jpeg');
    // $imagick->setImageBackgroundColor('white'); // 设置白色背景
    // $imagick = $imagick->flattenImages(); // 合并图层
    // 6. 转换为 WebP(强烈推荐,体积小、画质好)
    // $imagick->setImageFormat('webp');
    // 7. 写入文件
    $imagick->writeImage($destinationPath);
    $imagick->clear();
    return true;
}
// 使用示例
compressImageImagick('origin.png', 'compressed.webp', 80);
?>

优势总结

  • stripImage() 能去掉大量元数据。
  • 原生支持 WebP 转换,体积通常比 JPEG 小 25-35%。
  • 压缩质量更高,尤其低质量下比 GD 好。

使用第三方库(如 Intervention Image)

优点: 封装了 GD 和 Imagick,代码优雅、跨环境兼容。 缺点: 需要 Composer 安装。

安装(推荐在 Laravel 或 ThinkPHP 项目中使用):

composer require intervention/image

使用示例

use Intervention\Image\ImageManager;
// 选择驱动(根据服务器环境自动选择 GD 或 Imagick)
$manager = new ImageManager(['driver' => 'gd']); 
$image = $manager->make('origin.jpg');
// 压缩并保存
$image->resize(800, null, function ($constraint) {
    $constraint->aspectRatio();
    $constraint->upsize(); // 不放大
})
->save('compressed.jpg', 75); // 第二个参数是质量
// 转 WebP 保存
$image->encode('webp', 75)->save('compressed.webp');

调用外部 API / 云服务(大规模、高性能)

如果你的项目需要处理海量图片,或者不想占用服务器 CPU,推荐使用云服务:

  1. TinyPNG / TinyJPG API (tinify)

    • 效果极佳,带有损压缩,视觉无损。
    • 安装包:composer require tinify/tinify
    • 每月免费 500 张,超出付费。
    \Tinify\setKey('YOUR_API_KEY');
    $source = \Tinify\fromFile('origin.jpg');
    $source->toFile('compressed.jpg');
  2. 七牛云 / 阿里云 OSS / 腾讯云 COS 的图片处理管道

    • 上传后,通过 URL 参数或样式处理(如 ?imageMogr2/quality/70)。
    • 优点:完全不占用服务器资源,CDN 加速,支持多种裁剪缩放。

总结建议

场景 推荐方案 理由
简单的头像/缩略图压缩 GD 库 PHP 自带,无需配置,代码几行搞定。
高质量、专业级压缩 (WebP) Imagick 功能最强,支持格式广,压缩效果最好。
Laravel / 追求代码优雅 Intervention 封装好,易读,切换驱动方便。
服务器性能紧张 / 大规模处理 外部 API (TinyPNG) 节省 CPU,效果极致且视觉无损。
国内大厂云环境 OSS / COS 图片处理 不占服务器资源,结合 CDN,速度快。

最佳实践流程

  1. 用户上传图片。
  2. 限制最大尺寸(比如宽高不超过 1920px,这一步对体积影响最大)。
  3. 使用 ImagickIntervention 进行压缩,质量设为 80。
  4. 将图片转为 WebP 格式保存。
  5. 删除原始文件(或缩小后保存为备份)。

这样可以在肉眼几乎看不出差别的情况下,将图片体积减少 60% - 80%。

抱歉,评论功能暂时关闭!