php-vips会在可能的情况下只读取您需要的部分。它通常比imagemagick快3倍到5倍,并且需要更少的内存。
许多图像格式不允许随机访问。 JPEG、PNG、GIF和许多其他格式将强制您至少解压缩要处理的像素之前的像素,对于您正在处理的大型图像而言,这将非常缓慢。
一种解决方案是切换到JPEG压缩的平铺式TIFF。该格式将图像分成(默认情况下)256x256个像素的瓷砖,并单独压缩每个瓷砖。瓷砖存储在带有索引的TIFF文件中,因此您可以非常快速地提取单个瓷砖。
例如,您可以使用libvips将巨大的JPEG图像转换为JPEG压缩的平铺式tiff:
$ time vips copy wac_nearside.jpg wac_nearside.tif[tile,compression=jpeg]
real 0m3.891s
user 0m6.332s
sys 0m0.198s
peak RES 40mb
索引会使图像略微变大,但并不太糟糕:
$ ls -l wac_nearside.*
-rw-r--r-- 1 john john 74661771 May 7 2015 wac_nearside.jpg
-rw-r--r-- 1 john john 76049323 Feb 24 15:39 wac_nearside.tif
$ vipsheader wac_nearside.jpg wac_nearside.jpg: 24000x24000 uchar, 1 band, b-w, jpegload
您可以在PHP中像这样读取它的随机区域:
<?php
require __DIR__ . '/vendor/autoload.php';
use Jcupitt\Vips;
$image = Vips\Image::newFromFile($argv[1]);
$region_width = 100;
$region_height = 100;
for ($i = 0; $i < 100; $i++) {
$left = rand(0, $image->width - $region_width - 1);
$top = rand(0, $image->height - $region_height - 1);
$region = $image->crop($left, $top, $region_width, $region_height);
$region->writeToFile($i . ".jpg");
}
我可以这样运行那个程序:
$ time ./crop.php ~/pics/wac_nearside.tif
real 0m0.207s
user 0m0.181s
sys 0m0.042s
peak RES 36mb
在这台老旧的笔记本电脑上,它仅用0.2秒多一点的时间读取(并创建)100个JPEG文件。