This post was updated 675 days ago and some of the ideas may be out of date.

代码

<?php

/**
 * Created by PhpStorm.
 * User: LinFei
 * Created time 2023/02/22 22:55:11
 * E-mail: fly@eyabc.cn
 */
declare (strict_types=1);

class ImageColorAnalyzer
{
    /**
     * 获取图片的主色调 | Get the main color of the image
     * @param string $imagePath 图片路径或URL | Image path or URL
     * @return array
     */
    public static function getThemeColor(string $imagePath): array
    {
        // 创建 GD 图像对象
        $image = @imagecreatefromstring(static::getImageData($imagePath));

        if (!$image) {
            throw new InvalidArgumentException('Invalid image path or URL');
        }

        // 缩放图像
        $scaledImage = imagescale($image, 1, 1);

        // 获取所有像素的颜色
        $colorIndex = imagecolorat($scaledImage, 0, 0);
        $colorComponents = imagecolorsforindex($scaledImage, $colorIndex);

        // 创建颜色数组
        $colorArray = [
            [$colorComponents['red'], $colorComponents['green'], $colorComponents['blue']]
        ];

        // 聚类分析颜色
        $colorClusters = [];
        foreach ($colorArray as $color) {
            $closestCluster = null;
            $closestDistance = null;
            foreach ($colorClusters as $i => $cluster) {
                $distance = static::calculateColorDistance($color, $cluster);
                if ($closestDistance === null || $distance < $closestDistance) {
                    $closestDistance = $distance;
                    $closestCluster = $i;
                }
            }
            if ($closestDistance < 50) {
                $colorClusters[$closestCluster][] = $color;
            } else {
                $colorClusters[] = [$color];
            }
        }

        // 找到最常见的颜色
        $mostFrequentCluster = null;
        $mostFrequentCount = null;
        foreach ($colorClusters as $cluster) {
            $count = count($cluster);
            if ($mostFrequentCount === null || $count > $mostFrequentCount) {
                $mostFrequentCount = $count;
                $mostFrequentCluster = $cluster;
            }
        }

        // 十六进制颜色代码
        $hexColor = sprintf("#%02x%02x%02x", $mostFrequentCluster[0][0], $mostFrequentCluster[0][1], $mostFrequentCluster[0][2]);

        return [
            'hex' => $hexColor,
            'rgb' => $mostFrequentCluster[0]
        ];
    }

    /**
     * 计算两个颜色之间的距离 | Calculate the distance between two colors
     * @param array $color1 颜色1 | Color 1
     * @param array $color2 颜色2 | Color 2
     * @return float
     */
    private static function calculateColorDistance(array $color1, array $color2): float
    {
        $redMean = ($color1[0] + $color2[0]) / 2;
        $redDiff = $color1[0] - $color2[0];
        $greenDiff = $color1[1] - $color2[1];
        $blueDiff = $color1[2] - $color2[2];
        return sqrt((2 + $redMean / 256) * ($redDiff ** 2) + 4 * ($greenDiff ** 2) + (2 + (255 - $redMean) / 256) * ($blueDiff ** 2));
    }

    /**
     * 获取图片数据 | Get image data
     * @param string $path
     * @return string
     */
    private static function getImageData(string $path): string
    {
        return (string)file_get_contents($path);
    }
}

调用

$color = ImageColorAnalyzer::getThemeColor('https://img.eyabc.cn/images/2023/02/15/j501zo.jpg');
var_dump($color);

// array(2) {
//     ["hex"]=>
//   string(7) "#ccd1d4"
//     ["rgb"]=>
//   array(3) {
//         [0]=>
//     int(204)
//     [1]=>
//     int(209)
//     [2]=>
//     int(212)
//   }
// }