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.