How to Get Dominant Colours of an Image in PHP

on in Blog | Last modified on

Dominant Color

This feature has been requested by some of my ImagePress customers. It is also being used on my PropertyPin website. Basically, whenever a new image is uploaded, an array of 8 primary colours is extracted and a dominant colour is set.

The 8 primary colours are rounded up, so, for example, a bunch of red shades will be slightly adjusted to have the exact hex code.

Let’s see how I did it, using PHP. Note that, in the code below, I kept both rounded and non-rounded values, as your requirements might vary.

function extract_colors($image, $num, $level = 5) {
    $level = (int) $level;
    $palette = [];
    $size = getimagesize($image);

    if (!$size) {
        return true;
    }

    $img = imagecreatefromstring(file_get_contents($image));

    if (!$img) {
        return true;
    }

    for ($i = 0; $i < $size[0]; $i += $level) {
        for ($j = 0; $j < $size[1]; $j += $level) {
            $thisColor = imagecolorat($img, $i, $j);
            $rgb = imagecolorsforindex($img, $thisColor); 

            // With rounding
            $color = sprintf(
                '%02X%02X%02X',
                round(round(($rgb['red'] / 0x33)) * 0x33),
                round(round(($rgb['green'] / 0x33)) * 0x33),
                round(round(($rgb['blue'] / 0x33)) * 0x33)
            );

            // Without rounding
            /*
            $color = sprintf(
                '%02X%02X%02X',
                $rgb['red'],
                $rgb['green'],
                $rgb['blue']
            );
            /**/

            $palette[$color] = isset($palette[$color]) ? ++$palette[$color] : 1;
        }
    }

    arsort($palette);

    return array_slice(array_keys($palette), 0, $num);
}

Next, let’s use the function above and extract colours from an image.

$img = 'path/to/image.jpg';

// Extract 8 primary colours
$palette = extract_colors($img, 8, 1);

echo '<table>'; 

foreach ($palette as $color) { 
    echo '<tr><td style="background: #' . $color . '; width:36px;"></td><td>#' . $color . '</td></tr>';
} 

echo '</table>';

We now have a neat table with 8 colours. We can do whatever we want with them. In my case, with ImagePress, I built a search-by-colour feature, pretty useful right now, and seen in action on Dribbble, Behance, or even ArtStation.

Next, let’s extract the dominant colour

function extract_dominant_colour($image) {
    $info = getimagesize($image);
    $mime = $info['mime'];

    switch ($mime) {
        case 'image/jpeg':
            $image_create_func = 'imagecreatefromjpeg';
            break;
        case 'image/png':
            $image_create_func = 'imagecreatefrompng';
            break;
        case 'image/gif':
            $image_create_func = 'imagecreatefromgif';
            break;
    }

    $avg = $image_create_func($image);
    list($width, $height) = getimagesize($image);
    $tmp = imagecreatetruecolor(1, 1);
    imagecopyresampled($tmp, $avg, 0, 0, 0, 0, 1, 1, $width, $height);

    $rgb = imagecolorat($tmp, 0, 0);
    $r = ($rgb >> 16) & 0xFF;
    $g = ($rgb >> 8) & 0xFF;
    $b = $rgb & 0xFF;

    return sprintf("#%02x%02x%02x", $r, $g, $b);
}

Now let’s use the code:

$img = 'path/to/image.jpg';

$dominant_colour = extract_dominant_colour($img);

echo '<div style="display:inline-block; width:auto; height:400px; margin:8px; padding:24px; box-sizing:border-box; background-color:' . $dominant_colour . ';">';
echo '<img style="width:auto; max-height:100%; max-width: 100%; height:auto;" src="' . $img . '">';
echo '</div>';

Before using the code above, I used a WordPress plugin based on the Color Thief library with thousands and thousands of lines of code.

Related Posts

Leave a Reply

Your email address will not be published. Required fields are marked *