这是使用php-vips 的解决方案。它非常快,并且会找到最常见的颜色,而不是平均颜色。
大多数照片都会以灰色作为平均值,因为这就是自动白平衡的作用。你真正想要的是最常出现的颜色。
此程序使用 3D 直方图。它制作了一个 10 x 10 x 10 的立方体(您可以更改它,请参阅$n_bins)来表示整个 RGB 色彩空间,然后循环遍历图像,计算落入每个 bin 的像素数。它将 bin (0, 0, 0) 中的计数设置为零(黑色通常是无趣的背景),然后搜索具有最高计数的 bin。该 bin 的索引是最常见的 RGB 颜色。
这不适用于大多数 PNG(您需要拉平 alpha)或 CMYK(您需要先转换为 RGB)。
#!/usr/bin/env php
<?php
require __DIR__ . '/vendor/autoload.php';
use Jcupitt\Vips;
$im = Vips\Image::newFromFile($argv[1], ['access' => 'sequential']);
# 3D histogram ... make 10 x 10 x 10 bins, so 1000 possible colours
$n_bins = 10;
$hist = $im->hist_find_ndim(['bins' => $n_bins]);
# black is usually background or boring, so set that cell to 0 counts
# fetch (0, 0, set the 0th element of that to 0, paste back
$pixel = $hist->getpoint(0, 0);
$pixel[0] = 0;
$pixel = Vips\Image::black(1, 1)->add($pixel);
$hist = $hist->insert($pixel, 0, 0);
# (x, y) pixel with the most counts
[$v, $x, $y] = $hist->maxpos();
$pixel = $hist->getpoint($x, $y);
$z = array_search($v, $pixel);
# convert indexes to rgb ... +0.5 to get the centre of each bin
$r = ($x + 0.5) * 256 / $n_bins;
$g = ($y + 0.5) * 256 / $n_bins;
$b = ($z + 0.5) * 256 / $n_bins;
echo("r = " . $r . "\n");
echo("g = " . $g . "\n");
echo("b = " . $b . "\n");
我可以这样运行:
$ time ./try302.php ~/pics/shark.jpg
r = 38.4
g = 38.4
b = 12.8
real 0m0.077s
user 0m0.068s
sys 0m0.016s
在这台普通的笔记本电脑上,700 x 700 像素的 jpg 需要 70 毫秒。