首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >PHP 高效图像处理库 libvips,内存需求低到离谱!

PHP 高效图像处理库 libvips,内存需求低到离谱!

作者头像
Tinywan
发布2026-07-01 17:43:50
发布2026-07-01 17:43:50
730
举报
文章被收录于专栏:开源技术小栈开源技术小栈

简介

php-vips 是 libvips 8.7 及后续版本的 PHP 绑定,支持 PHP 7.4 及以上版本。

libvips 非常快且内存占用极低。vips-php-bench 仓库将 php-vipsimagickgd 进行测试。在笔记本电脑上测试结果显示,php-vipsimagick 快约 4 倍,内存占用仅为后者的 1/10。

使用 libvips 的程序不会直接操作图像,而是从源图像开始构建图像处理操作管道。当管道连接到目标时,整个管道会一次性并行执行,并以小片段流的形式从源图像传输到目标图像。

安装

你需要先安装 libvips 库。它在 Linux 包管理器、Homebrew 和 MacPorts 中都有,在 vips 官网提供 Windows 二进制文件。例如,在 Debian 上:

代码语言:javascript
复制
sudo apt-get install --no-install-recommends libvips42

--no-install-recommends 可防止 Debian 安装大量额外包)

或者在 macOS 上:

代码语言:javascript
复制
brew install vips

你需要在 PHP 中启用 FFI(请参阅 PHP FFI 配置),然后将 vips 添加到你的 composer.json 中:

代码语言:javascript
复制
"require": {
    "jcupitt/vips": "2.4.0"
}

php-vips 目前不支持预加载,因此你需要在全局启用 FFI。这存在一些安全隐患,因为你的服务器上运行 PHP 的任何人都可以调用他们有权访问的任何本机库。

当然,如果攻击者已经在你的 Web 服务器上运行自己的 PHP 代码,你很可能已经中招了,不幸的是……

最后,在 PHP 8.3 及以上版本,你需要禁用栈溢出测试。php-vips 在主线程之外执行 FFI 回调,这会混淆这些检查(至少在 PHP 8.3.0 中)。

在你的 php.ini 中添加:

代码语言:javascript
复制
zend.max_allowed_stack_size=-1

示例

代码语言:javascript
复制
#!/usr/bin/env php
<?php
require __DIR__ . '/vendor/autoload.php';
use Jcupitt\Vips;

// Windows 快捷方式
Vips\FFI::addLibraryPath("C:/vips-dev-8.16/bin");

// 检查 libvips 版本
echo 'libvips version: ' . Vips\Config::version() . PHP_EOL;

// 快速缩略图生成器
$image = Vips\Image::thumbnail('somefile.jpg', 128);
$image->writeToFile('tiny.jpg');

// 加载图像、获取字段、处理、保存
$image = Vips\Image::newFromFile($argv[1]);
echo "width = $image->width\n";
$image = $image->invert();
$image->writeToFile($argv[2]);

运行方式:

代码语言:javascript
复制
$ composer install
$ ./try1.php ~/pics/k2.jpg x.tif

请查看 examples/。我们有完整的格式化 API 文档。

工作原理

php-vips 使用 php-ffi 直接调用 libvips 二进制文件。它会内省库二进制文件,并将找到的方法作为 Image 类中的成员呈现。

这意味着你看到的 API 取决于 php-vips 在运行时找到的 libvips 版本,而不是取决于 php-vips 本身。php-vips 文档假设你使用的是最新稳定的 libvips 库版本。

之前的 php-vips 版本依赖二进制扩展而不是 php-ffi,在 1.x 分支 仍然可用并受支持。

API 介绍

几乎所有方法都会返回一个新图像作为结果,因此你可以链式调用。例如:

代码语言:javascript
复制
$new_image = $image->more(12)->ifthenelse(255, $image);

会生成大于 12 的像素掩码,然后使用该掩码将像素设置为 255 或原始图像。

注意,libvips 操作始终创建新图像,它们不会修改现有图像,因此在上面一行之后,$image 保持不变。

你可以将 long、double、array 和 image 作为参数。例如:

代码语言:javascript
复制
$image = $image->add(2);

将 2 添加到每个波段元素,或者:

代码语言:javascript
复制
$image = $image->add([1, 2, 3]);

将 1 添加到第一个波段,2 添加到第二个,3 添加到第三个。或者:

代码语言:javascript
复制
$image = $image->add($image2);

添加两个图像。或者:

代码语言:javascript
复制
$image = $image->add([[1, 2, 3], [4, 5, 6]]);

从数组创建一个 3x2 图像,然后将其添加到原始图像。

几乎所有方法都可以接受额外的最终参数:一个选项数组。例如:

代码语言:javascript
复制
$image->writeToFile("fred.jpg", ["Q" => 90]);

php-vips 附带 API 文档。要从源代码重新生成这些文档,请运行:

代码语言:javascript
复制
$ vendor/bin/phpdoc

不幸的是,由于 php-doc 限制,这些文档不会列出每个操作的所有选项。要获取完整 API 描述,你需要查看主 libvips 文档:

https://libvips.org/API/current

测试和安装

代码语言:javascript
复制
$ composer install
$ composer test
$ vendor/bin/phpdoc
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2026-06-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 开源技术小栈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 简介
  • 安装
  • 示例
  • 工作原理
  • API 介绍
  • 测试和安装
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档