2

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:

enter image description here

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?

Appel Flap
  • 261
  • 3
  • 23
  • 1
    Is this any use? https://stackoverflow.com/questions/596216/formula-to-determine-brightness-of-rgb-color – Progrock Nov 09 '19 at 15:31

2 Answers2

1

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?

Professor Abronsius
  • 33,063
  • 5
  • 32
  • 46
  • Yes, this is exactly what I'm looking for! Is it possible to modify this code so it only scans for the dominant color, without looping multiple times? – Appel Flap Nov 09 '19 at 18:20
  • I don't think that it would be possible - afterall you don't know ( or the script doesn't know ) the dominant colour without analysing it so I can see any shortcuts to deducing that unknown without inspecting each pixel – Professor Abronsius Nov 09 '19 at 20:07
1

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 ...

JonoJames
  • 1,117
  • 8
  • 22
  • 1
    Thank you for your answer and the explanation, JonoJames! The answer of RamRaider aims more towards a solution of what I've been trying to achieve with this, but your answer certainly adds to the value of this question. Thanks again! – Appel Flap Nov 09 '19 at 18:26