24 мая 2011 г.

Рисуем градиент на PHP

Как-то мне поступил заказ, чтобы я сделал выбор цвета как в Photoshop. Конечно, один в один я его не сделал, ну, этого и не требовалось, но суть не в этом. Для того, чтобы осуществить нечто подобное, необходимо знать по какому цвету ты щелкаешь. Для этого оказалось проще самому программным образом нарисовать такой квадратик, тогда я буду на 100% уверен какой пиксель, какой цвет содержит. Т.е. его шестнадцатеричный код.
Вот, что у меня получилось.

Теперь я продемонстрирую сам код:
<?php
$im = imagecreatetruecolor(128,128);
$dec_r = 0;
$dec_g = 2;
$dec_b = 2;
for($y = 0; $y < 128; $y++){
 $red = 255;
 $green = 255;
 $blue = 255;
 if($y < 22) $dec_g = (256 - $y * 12) / 128;
 else if($y > 21 && $y < 43){
  $dec_g = 0;
  $dec_r = ($y * 12 - 256) / 128;
 }
 else if($y > 42 && $y < 65){
  $dec_r = 2;
  $dec_b = (768 - $y * 12) / 128;
 }
 else if($y > 64 && $y < 86){
  $dec_b = 0;
  $dec_g = ($y * 12 - 768) / 128;
 }
 else if($y > 85 && $y < 107){
  $dec_g = 2;
  $dec_r = (1280 - $y * 12) / 128;
 }
 else if($y > 106){
  $dec_r = 0;
  $dec_b = ($y * 12 - 1280) / 128;
 }
 for($x = 0; $x < 128; $x++){
  $color_now = imagecolorallocate($im, round($red - $x * $dec_r), round($green - $x * $dec_g),round($blue - $x * $dec_b));
  imagesetpixel($im, $x, $y, $color_now);
 }
}

header("Content-type: image/png");
imagepng($im);
imagedestroy($im);
?>

Тут логика проста. Создаем изображение размером 128х128. Потом для каждой строчки определяем правило, по которому будут происходить изменения цвета каждого следующего пикселя.
Переменные $dec_r, $dec_g, $dec_b отвечают за шаг каждого цвета. Т.е. сначала у нас $dec_r = 0, $dec_g = 2 и $dec_b = 2. Это означает, что красный цвет изменятся не будет. А зеленый и синий будут уменьшаться на 2. Так будет только в первой строчке. Во второй правило изменится для шага зеленого цвета. Его шаг замедлится и не достигнет нуля. Таким образом, в конце второй строчки у нас уже будет не чистый красный цвет, а начнет приближаться к желтому. На 21-й строчке значение зеленого цвета практический перестает изменятся и, начиная с 22-й строчке оно будет равно 255. Но теперь начинает увеличиваться шаг красного цвета, когда он достигнет 2, начинает уменьшаться шаг синего цвета и т.д. Таким образом, мы пройдем по всей цветовой гамме. Конечно, частота дискретизации не позволит нам сделать это более плавно уместившись в такой маленький участок экрана, но наш глаз скачков цвета не заметит.

Дорогие читатели. В следующей статье я хочу вам рассказать о том, как осуществить выбор цвета как в photoshop на javascript. Если же вас интересуют другие темы, то пишите, обсудим.
До новых встреч!

3 комментария:

  1. Я смотрю Вы отлично разбираетесь в web-программировании! Всегда с удовольствие читаю такие блоги, т.к. описанные приемы можно применить на практике и поэкспериментировать :)

    ОтветитьУдалить
  2. Спасибо, отличный пример! Мне понадобилось вынести вычисление цвета за цикл, для этого чуть чуть поправил расчёт, может быть кому пригодится. На выходе - цвет в формате #ffffff.

    function get_spectrum_color($spectrum_percent, $brightness_percent = 50)
    {
    $dec_r = 0;
    $dec_g = 2;
    $dec_b = 2;

    if ($spectrum_percent >= 0 && $spectrum_percent <= 100) {
    $y = round($spectrum_percent * 127 / 100);
    }
    else {
    $y = rand(0, 127);
    }

    if ($brightness_percent >= 0 && $brightness_percent <= 100) {
    $x = round($brightness_percent * 127 / 100);
    }
    else {
    $x = rand(0, 127);
    }

    $red = 255;
    $green = 255;
    $blue = 255;

    if ($y < 22) {
    $dec_g = (256 - $y * 12) / 128;
    }
    elseif ($y > 21 && $y < 43) {
    $dec_g = 0;
    $dec_r = ($y * 12 - 256) / 128;
    }
    elseif ($y > 42 && $y < 65) {
    $dec_r = 2;
    $dec_b = (768 - $y * 12) / 128;
    $dec_g = 0;
    }
    elseif ($y > 64 && $y < 86) {
    $dec_b = 0;
    $dec_g = ($y * 12 - 768) / 128;
    $dec_r = 2;
    }
    elseif ($y > 85 && $y < 107) {
    $dec_g = 2;
    $dec_r = (1280 - $y * 12) / 128;
    $dec_b = 0;
    }
    elseif ($y > 106) {
    $dec_r = 0;
    $dec_b = ($y * 12 - 1280) / 128;
    }

    $red_hex = dechex(round($red - $x * $dec_r));
    $red_hex = strlen($red_hex) > 1 ? $red_hex : '0'.$red_hex;

    $green_hex = dechex(round($green - $x * $dec_g));
    $green_hex = strlen($green_hex) > 1 ? $green_hex : '0'.$green_hex;

    $blue_hex = dechex(round($blue - $x * $dec_b));
    $blue_hex = strlen($blue_hex) > 1 ? $blue_hex : '0'.$blue_hex;

    $color_now = '#' . $red_hex . $green_hex . $blue_hex;
    return $color_now;
    }

    ОтветитьУдалить