Вычисление среднего цвета между двумя цветами в PHP, используя номер индекса в качестве эталонного значения

В PHP я пытаюсь вычислить средний цвет (в гексагоне) между разными шестнадцатеричными цветами. Тем не менее, я также должен иметь возможность указывать номер индекса от 0,0 до 1,0.

Так, например:

у меня есть

$color1 = "#ffffff" $color2 = "#0066CC" 

Если бы я написал функцию, чтобы получить средний цвет, и я бы поставил 0.0 в качестве номера индекса, функция должна была бы вернуть « #ffffff ». Если бы я поставил 1.0 в качестве номера индекса, функция должна была бы вернуть « #0066CC ». Однако, если бы я поставил 0.2, функция должна была бы вернуть средний цвет между двумя цветами, но все же ближе к $color1 чем к $color2 . Если бы я поставил индекс номер 0.5, я бы получил точный средний цвет обоих цветов.

Я пытался это сделать уже несколько дней, но я не могу понять это! Любая помощь была бы поэтому очень признательна!

Предположим, что каждый цвет имеет «ценность» для целей этого обсуждения. Тогда то, что вы хотите, было бы достаточно простым:

 $index = 0.2; $val1 = get_value_of_color($color1); $val2 = get_value_of_color($color2); $newval = $val1 * $index + $val2 * (1 - $index); $newcolor = get_color_from_value($newval); 

Итак, сложная часть – это то, что означает «ценность» каждого цвета.

Вы можете использовать простые значения RGB, где «значение» каждого цвета представляет собой набор из трех целых чисел:

 function get_value_of_color($color) { // assume $color is in the form #xxxxxx return array( hexdec(substr($color, 1, 2)), hexdec(substr($color, 3, 2)), hexdec(substr($color, 5, 2)), ); } function get_color_from_value($value) { return sprintf('#%02x%02x%02x', $value[0], $value[1], $value[2]); } 

Для каждого элемента массива отдельно нужно будет умножать и добавлять. Я думаю, в этот момент было бы легко сделать простую в использовании функцию для смешивания цветов.

Если это не то, что вам нужно, вы можете использовать значения HSL или некоторые другие показатели, которые лучше подходят для вашего приложения. Идея останется прежней.

Я не уверен, скомпилирует ли он, но если вы хотите, чтобы математика стояла за этим, это выглядело бы так:

Для простоты всегда есть $color1 больше $color2 .

 $dec1 = hexdec($hex_color1); $dec2 = hexdec($hex_color2); $dec1 = ($dec1 < $dec2) ? $dec1^=$dec2^=$dec1^=$dec2 : $dec1; $new_hex_color = dechex($dec1 - ($dec1 - $dec2)*index_number) 

Можешь попробовать:

 function color_avg($color1,$color2,$factor) { // extract RGB values for color1. list($r1,$g1,$b1) = str_split(ltrim($color1,'#'),2); // extract RGB values for color2. list($r2,$g2,$b2) = str_split(ltrim($color2,'#'),2); // get the average RGB values. $r_avg = (hexdec($r1)*(1-$factor)+hexdec($r2)*$factor); $g_avg = (hexdec($g1)*(1-$factor)+hexdec($g2)*$factor); $b_avg = (hexdec($b1)*(1-$factor)+hexdec($b2)*$factor); // construct the result color. $color_avg = '#'.sprintf("%02s",dechex($r_avg)). sprintf("%02s",dechex($g_avg)). sprintf("%02s",dechex($b_avg)); // return it. return $color_avg; } 

Видеть это

Я пробовал это, используя перечисленные выше функции:

 /* 24-bit RGB */ /* (a + b) / 2 = ((a ^ b) >> 1) + (a & b) */ function averageRGB($a, $b){ return ((($a ^ $b) & 0xfffefefe) >> 1) + ($a & $b); } $index = 0.5; $val1 = get_value_of_color('#FFFFFF'); $val2 = get_value_of_color('#000000'); $aIndexed = array(); for($i=0; $i < 3; $i++){ if($index == 0.5){ $aIndexed[$i] = averageRGB($val1[$i],$val2[$i]); }else{ $aIndexed[$i] = $val1[$i] * $index + $val2[$i] * (1 - $index); } } echo get_color_from_value($aIndexed); 
 function colorDiff($color1,$color2) { $color1= ltrim($color1,'#'); $color2= ltrim($color2,'#'); $red1 = hexdec(substr($color1,0,2)); $green1 = hexdec(substr($color1,2,2)); $blue1 = hexdec(substr($color1,4,2)); $red2 = hexdec(substr($color2,0,2)); $green2 = hexdec(substr($color2,2,2)); $blue2 = hexdec(substr($color2,4,2)); $red = dechex(round(($red1+$red2)/2)); $green = dechex(round(($green1+$green2)/2)); $blue = dechex(round(($blue1+$blue2)/2)); if (strlen($red) == 1) { $red = '0'.$red; } if (strlen($green) == 1) { $green = '0'.$green; } if (strlen($blue) == 1) { $blue = '0'.$blue; } $newcolor = '#'.$red.''.$green.''.$blue; return $newcolor; } 

Или используя массив в качестве входных данных:

  $color_arr = array('#FF0000','#0000FF','#FF0000','#0000FF','#0000FF','#0000FF'); $newcolor = colorDiffArr($color_arr); foreach ($color_arr as $color) { echo '<div style="display:block; background:'.$color.';" bgcolor="'.$color.'; width:10px; height:10px;">'.$color.'</div>'; } echo '<div style="display:block; background:'.$newcolor.';" bgcolor="'.$newcolor.'; width:10px; height:10px;">'.$newcolor.'</div>'; function colorDiffArr($color_arr) { $red = 0; $green = 0; $blue = 0; foreach ($color_arr as $color) { $color= ltrim($color,'#'); $red+=hexdec(substr($color,0,2)); $green+=hexdec(substr($color,2,2)); $blue+=hexdec(substr($color,4,2)); } $red = dechex(round(($red)/count($color_arr))); $green = dechex(round(($green)/count($color_arr))); $blue = dechex(round(($blue)/count($color_arr))); if (strlen($red) == 1) { $red = '0'.$red; } if (strlen($green) == 1) { $green = '0'.$green; } if (strlen($blue) == 1) { $blue = '0'.$blue; } $newcolor = '#'.$red.''.$green.''.$blue; return $newcolor; }