Reputation: 271
Now I've been searching around online on how to do this, but there doesn't seem to be a single question/answer to this.
I'm using a script to get the 6 main colors from a given image.
function detectColors($image, $num, $level = 5)
{
$level = (int) $level;
$palette = array();
$size = getimagesize($image);
if (!$size) {
return FALSE;
}
switch ($size['mime']) {
case 'image/jpeg':
$img = imagecreatefromjpeg($image);
break;
case 'image/png':
$img = imagecreatefrompng($image);
break;
case 'image/gif':
$img = imagecreatefromgif($image);
break;
default:
return FALSE;
}
if (!$img) {
return FALSE;
}
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);
$color = sprintf('%02X%02X%02X', (round(round(($rgb['red'] / 0x33)) * 0x33)), round(round(($rgb['green'] / 0x33)) * 0x33), round(round(($rgb['blue'] / 0x33)) * 0x33));
$palette[$color] = isset($palette[$color]) ? ++$palette[$color] : 1;
}
}
arsort($palette);
return array_slice(array_keys($palette), 0, $num);
}
$img = 'https://gs2-sec.ww.prod.dl.playstation.net/gs2-sec/appkgo/prod/CUSA03041_00/15/i_2efe1b71a037233f60cec3b41a18d69c02bcff5fd0c895c212d44f37883dbaf8/i/icon0.png';
$palette = detectColors($img, 6, 5);
echo '<img src="' . $img . '" />';
echo '<table>';
foreach($palette as $color) {
echo '<tr><td style="background:#' . $color . '; width:36px;"></td><td>#' . $color . '</td></tr>';
}
echo '</table>';
This will output a color palette:
What I would like to do with these colors, is finding out which one is the brighest, aka the dominant color, in this case the second color "CC0000". Of course excluding white #FFFFFF and black #000000.
My question being, how can I get the brightest color from an array of colors in PHP?
Upvotes: 2
Views: 835
Reputation: 1223
Ok Hex colors work from darkest to lightest being 012345679ABCDEF and they broken up in 2 characters representing Red Green Blue that's why a RGB color value is is made up of 6 characters
So you need a function to to compare the values and return the highest . Im not using and array but you can compare 2 values at a time with this function and adjust it to use an array .
function GetBrightest($first_color,$Second_color) {
//echo $first_color;
//remove the hash #
$first = $a = str_replace('#', '', $first_color);
$second = $a = str_replace('#', '', $Second_color);
$split_first = str_split($first, 2);
$split_second = str_split($second, 2);
print_r( $split_first);
print_r( $split_second);
//is red brighter
$r = ( $split_first[0] > $split_second[0] ? 1: 0);
$g = ( $split_first[1] > $split_second[1] ? 1: 0);
$b = ( $split_first[2] > $split_second[2] ? 1: 0);
//add the booleans
$t = $r+$g+$b;
if($t > 2 )
{
return $first_color;
}
else
{
return $Second_color;
}
} $Color = GetBrightest('#aa4444','#ff3333'); echo $Color;
The comparison I have done here is a rough comparison so you could refine the method as 2 of the 3 array values could be bigger however if the difference is vast in one color it would make it brighter
FF0000 and 991111 in this function will return the second color because Green and Blue is brighter however the red is very bright in the first value .
So you can refine it from there ...
Upvotes: 1
Reputation: 33804
If I understood correctly then perhaps you could approach the problem like this?
function detectColors( $image, $num, $level = 5 ) {
$level = (int)$level;
$palette = array();
$details = array();# store the count of non black or white colours here ( see $exclusions )
list( $width, $height, $type, $attr )=getimagesize( $image );
if( !$type ) return FALSE;
switch ( image_type_to_mime_type( $type ) ) {
case 'image/jpeg':
$img = imagecreatefromjpeg( $image );
break;
case 'image/png':
$img = imagecreatefrompng( $image );
break;
case 'image/gif':
$img = imagecreatefromgif( $image );
break;
default: return FALSE;
}
if( !$img ) return FALSE;
/* Colours to not factor into dominance statistics */
$exclusions=['000000','FFFFFF'];
for( $i = 0; $i < $width; $i += $level ) {
for( $j = 0; $j < $height; $j += $level ) {
$colour = imagecolorat( $img, $i, $j );
$rgb = imagecolorsforindex( $img, $colour );
$key = sprintf('%02X%02X%02X', ( round( round( ( $rgb['red'] / 0x33 ) ) * 0x33 ) ), round(round(($rgb['green'] / 0x33)) * 0x33), round(round(($rgb['blue'] / 0x33)) * 0x33));
$palette[ $key ] = isset( $palette[ $key ] ) ? ++$palette[ $key ] : 1;
if( !in_array( $key, $exclusions ) ){
/* add count of any non excluded colours */
$details[ $key ] = isset( $details[ $key ] ) ? ++$details[ $key ] : 1;
}
}
}
arsort( $palette );
/* prepare statistics for output */
$output=new stdclass;
$output->data=array_slice( array_keys( $palette ), 0, $num );
$output->highest=max( $details );
$output->lowest=min( $details );
$output->dominant=array_search( $output->highest, $details );
$output->recessive=array_search( $output->lowest, $details );
return $output;
}
$img = 'https://gs2-sec.ww.prod.dl.playstation.net/gs2-sec/appkgo/prod/CUSA03041_00/15/i_2efe1b71a037233f60cec3b41a18d69c02bcff5fd0c895c212d44f37883dbaf8/i/icon0.png';
$palette = detectColors( $img, 6, 5 );
$html=[];
foreach( $palette->data as $colour ) $html[]=sprintf( '<tr><td style="background:#%1$s; width:200px; height:1rem; " >#%1$s</td></tr>', $colour );
printf('
<p>Analysing: %1$s</p>
<img src="%1$s" />
<table>%2$s</table>
<ul>
<li>Dominant colour: %3$s - count: %4$d</li>
<li>Recessive colour: %5$s - count: %6$d</li>
</ul>',
$img,
implode( PHP_EOL, $html ),
$palette->dominant,
$palette->highest,
$palette->recessive,
$palette->lowest
);
Outputs:
Dominant colour: CC0000 - count: 3032
Recessive colour: 333366 - count: 1
Is that more or less what you were asking?
Upvotes: 1