Синий с желтым дадут зеленый только в CMY, а не в RGB. Вас не удивит ведь тот факт, что красный с зеленым в RGB дают желтый. Если дать смещение в сторону зеленого - тогда и получится зеленоватый оттенок (#0088FF + #FFFF00): При ресемплинге получится что-то типа #88CC88 Gimp показал цвет #80c080
Можно не уменьшать картинку, а просто делать репрезентативную выборку пикселей по всей площади! Я придумал выбирать N пикселей по случайным координатам. Когда n = 5000, функция дает стабильный топ-10 для реальных фоток. По-прежнему, опирается на собственные 256 оттенков. Размер фото больше не важен! Скрипт отрабатывает менее, чем за 5 секунд! В общем, записал свои идеи в одну функцию и готов передать права на неё за $20, если пригодится. PHP: <?php // (c) 2017 www.vasya.pro /** * * @param string $path путь к картинке * @param int $count количество цветов в результате * @param type $magic число анализируемых пикселей * @return array целочисленный индекс цвета => процент */ function getColorsProportions($path, $count = 10, $magic = 5000) { $data = file_get_contents($path); $image = imagecreatefromstring($data); unset($data); $w = imagesx($image); $h = imagesy($image); $sq = $w * $h; $colorats = []; for ($i = 0; $i < $magic; $i ++) { $pix = mt_rand(0, $sq); $y = (int) ($pix / $w); $x = $pix - $y * $w; $colorats[] = imagecolorat($image, $x, $y); } imagedestroy($image); $palette = []; for ($ir = 255; $ir >= 0; $ir -= 51) { for ($ig = 255; $ig >= 0; $ig -= 51) { for ($ib = 255; $ib >= 0; $ib -= 51) { if ($ir === $ig && $ig === $ib) { continue; } $palette[] = ($ir << 16) + ($ig << 8) + $ib; } } } for ($i = 0; $i <= 46; $i++) { $index = $i * 5.666666666666667; $palette[] = ($index << 16) + ($index << 8) + $index; } $getColor = function($ic, $palette) { $r1 = ($ic >> 16) & 0xFF; $g1 = ($ic >> 8) & 0xFF; $b1 = $ic & 0xFF; $distance = PHP_INT_MAX; foreach ($palette as $bc) { $r2 = ($bc >> 16) & 0xFF; $g2 = ($bc >> 8) & 0xFF; $b2 = $bc & 0xFF; $dist = sqrt(pow($r1 - $r2, 2) + pow($g1 - $g2, 2) + pow($b1 - $b2, 2)); if ($dist < $distance) { $distance = $dist; $color = $bc; } } return $color; }; $scores = []; foreach ($colorats as $ic) { $color = $getColor($ic, $palette); if (!isset($scores[$color])) { $scores[$color] = 0; } $scores[$color] ++; } arsort($scores); $palette = array_keys(array_slice($scores, 0, $count, true)); $total = []; foreach ($scores as $ic => $score) { $color = $getColor($ic, $palette); if (!isset($total[$color])) { $total[$color] = 0; } $total[$color] += $score; } arsort($total); $sum = array_sum($total); $percents = []; foreach ($total as $color => $score) { $percents[$color] = (100 / $sum) * $score; } return $percents; } /* TEST */ echo '<pre>'; $start = microtime(1); $res = getColorsProportions('image.jpg', 11); echo round((microtime(1) - $start), 3); foreach ($res as $rgb => $size) { $size = round($size * 10); $r = ($rgb >> 16) & 0xFF; $g = ($rgb >> 8) & 0xFF; $b = $rgb & 0xFF; echo '<div style="float: left; width: ' . $size . 'px; height: ' . $size . 'px;' . ' background-color:rgb(' . $r . ',' . $g . ',' . $b . ');"></div>'; } --- Добавлено --- На этом мой творческий потенциал в этой задаче исчерпан =)
я изложил свои мысли - масштабирование само смешает цвета и сделает это на низкоуровневых библиотеках, а не на PHP, --- Добавлено --- спасибо! буду изучать когда работа немного отпустит меня
нет, к сожалению. это требует времени и "переключения контекста". пока есть более приоритетные задачи