圖片網站常需根據用戶上傳圖片提取主色調,用于色系搜索、推薦、UI 自適應配色。傳統遍歷像素統計 RGB 頻率效率極低且不準。本文介紹基于 Imagick::quantizeImage() 降色量化算法的高效方案。
quantizeImage() 將圖片顏色空間減少到指定顏色數(如 10 色),自動聚類相似顏色,保留視覺上最具代表性的調色板。隨后 uniqueImageColors() 進一步去重,最終通過像素迭代器讀取剩餘顏色,即為主色調集合。
<?php
function getImageMainColors($imagePath, $colorCount = 10) {
if (!extension_loaded('imagick')) {
throw new RuntimeException('Imagick 擴展未安裝');
}
if (!file_exists($imagePath)) {
throw new InvalidArgumentException("圖片不存在: $imagePath");
}
$im = new Imagick($imagePath);
// 1. 縮略圖加速(可選,大圖建議先縮放至 200px 寬)
$im->thumbnailImage(200, 0, true);
// 2. 量化:減少到 $colorCount 種顏色,RGB 空間,無抖動,無樹深度限制
$im->quantizeImage($colorCount, Imagick::COLORSPACE_RGB, 0, false, false);
// 3. 去重唯一顏色
$im->uniqueImageColors();
// 4. 遍歷像素獲取 RGB
$colors = [];
$it = $im->getPixelIterator();
$it->resetIterator();
while ($row = $it->getNextIteratorRow()) {
foreach ($row as $pixel) {
$c = $pixel->getColor(); // ['r'=>255, 'g'=>128, 'b'=>0, 'a'=>255]
// 過濾透明度極低的顏色
if (($c['a'] ?? 255) > 128) {
$colors[] = "rgb({$c['r']},{$c['g']},{$c['b']})";
}
}
}
$im->destroy(); // 釋放內存
return array_unique($colors); // 去重
}
// 使用示例
try {
$mainColors = getImageMainColors('uploads/photo.jpg', 8);
echo "<div style='display:flex; gap:8px;'>";
foreach ($mainColors as $rgb) {
echo "<div style='width:40px;height:40px;background:$rgb;border:1px solid #ddd;' title='$rgb'></div>";
}
echo "</div>";
} catch (Exception $e) {
echo "錯誤: " . $e->getMessage();
}
?>
| 參數 | 建議值 | 說明 |
|---|---|---|
| $colorCount | 8-16 | 過少丟失細節,過多引入噪點。UI 配色 5-8 色足夠。 |
| COLORSPACE | COLORSPACE_RGB / LAB | LAB 空間更符合人眼感知,聚類效果更好,但需 ImageMagick 7+。 |
| dither | false | 關閉抖動避免引入不存在的中間色。 |
| thumbnailImage | 200px 寬 | 大圖(>1MB)量化極慢,預先縮略不影響主色調提取精度。 |
imagecolorstotal() + imagecolorsforindex() 讀取調色板(僅適用 GIF/PNG-8)。colors 參數直接返回主色調 JSON。