Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detect "overall average" color of the picture

I have a jpg image.

I need to know "overall average" the color of the image. At first glance there can use the histogram of the image (channel RGB).

At work I use mostly JavaScript and PHP (a little Python) therefore welcomed the decision in these languages. Maybe ther are library for working with images that address similar problems.

I do not need to dynamically determine the color of the picture. I need just once go through the entire array of images and determine the color of each separately (this information I will remember for future use).

like image 321
Kalinin Avatar asked Aug 12 '10 14:08

Kalinin


2 Answers

You can use PHP to get an array of the color palette like so:

<?php  function colorPalette($imageFile, $numColors, $granularity = 5)  {     $granularity = max(1, abs((int)$granularity));     $colors = array();     $size = @getimagesize($imageFile);     if($size === false)     {        user_error("Unable to get image size data");        return false;     }     $img = @imagecreatefromjpeg($imageFile);    // Andres mentioned in the comments the above line only loads jpegs,     // and suggests that to load any file type you can use this:    // $img = @imagecreatefromstring(file_get_contents($imageFile));      if(!$img)     {        user_error("Unable to open image file");        return false;     }     for($x = 0; $x < $size[0]; $x += $granularity)     {        for($y = 0; $y < $size[1]; $y += $granularity)        {           $thisColor = imagecolorat($img, $x, $y);           $rgb = imagecolorsforindex($img, $thisColor);           $red = round(round(($rgb['red'] / 0x33)) * 0x33);           $green = round(round(($rgb['green'] / 0x33)) * 0x33);           $blue = round(round(($rgb['blue'] / 0x33)) * 0x33);           $thisRGB = sprintf('%02X%02X%02X', $red, $green, $blue);           if(array_key_exists($thisRGB, $colors))           {              $colors[$thisRGB]++;           }           else           {              $colors[$thisRGB] = 1;           }        }     }     arsort($colors);     return array_slice(array_keys($colors), 0, $numColors);  }  // sample usage:  $palette = colorPalette('rmnp8.jpg', 10, 4);  echo "<table>\n";  foreach($palette as $color)  {     echo "<tr><td style='background-color:#$color;width:2em;'>&nbsp;</td><td>#$color</td></tr>\n";  }  echo "</table>\n"; 

Which gives you an array whose values are higher for how often that color has been used.

EDIT A commenter asked how to use this on all files in a directory, here it is:

    if ($handle = opendir('./path/to/images')) {          while (false !== ($file = readdir($handle))) {            $palette = colorPalette($file, 10, 4);            echo "<table>\n";             foreach($palette as $color) {                 echo "<tr><td style='background-color:#$color;width:2em;'>&nbsp;</td><td>#$color</td></tr>\n";             }             echo "</table>\n";         }         closedir($handle);     } 

might not want to do this on too many files, but it's your server.

Alternatively if you'd rather use Javascript Lokesh's Color-Theif library does exactly what you're looking for.

like image 140
JKirchartz Avatar answered Sep 22 '22 19:09

JKirchartz


Combining JKirchartz and Alexander Hugestrand answer:

 function getAverage($sourceURL){      $image = imagecreatefromjpeg($sourceURL);     $scaled = imagescale($image, 1, 1, IMG_BICUBIC);      $index = imagecolorat($scaled, 0, 0);     $rgb = imagecolorsforindex($scaled, $index);      $red = round(round(($rgb['red'] / 0x33)) * 0x33);      $green = round(round(($rgb['green'] / 0x33)) * 0x33);      $blue = round(round(($rgb['blue'] / 0x33)) * 0x33);      return sprintf('#%02X%02X%02X', $red, $green, $blue);   } 

Tried and tested, returns hex string.

like image 30
Johnny Rockex Avatar answered Sep 26 '22 19:09

Johnny Rockex