О кругах
![топ 100 блогов](/media/images/default.jpg)
Девочку шести лет приводят в школу. На собеседовании её спрашивают, сколько она знает времён года. Девочка на минутку задумывается и уверенно говорит:
— Шесть!..
Директор тактично ей намекает:
— А если подумать?.. Ну, подумай...
Девочка снова на мгновение зависает и говорит:
— Честное слово, больше не помню... Шесть!..
Директор выразительно смотрит на побагровевшую мамашу девочки, покашливает и отправляет их на минуточку в коридор. Там мама возмущенно спрашивает дочку:
— Ну, Лена, и что это было?!
— Мама, мама... — со слезами на глазах отвечает дочка, — я и правда не помню больше никаких «Времён года», кроме Вивальди, Гайдна, Пьяццола, Лусье, Чайковского и Глазунова!..
Мама:
— Лена! А Десятников, а Кейдж?!
Понадобился мне тут комплект из двенадцати цветов, чтобы покрасить каждый месяц в свой любимый цвет. Начал я гуглить и... внезапно узнал про цветовой круг. Что удивительно, этот самый круг известен гораздо дольше, чем интернет: на фотографиях в статье по ссылке — самый настоящий олдскульный картонный круг! Только вот раньше им пользовались профессионалы, а теперь — каждый второй профессионал: кто не вирусолог, тот дизайнер.
Впрочем, теоретические знания — это хорошо, но как получить требуемый набор? В том же блоге есть замечательная статья про цветовые схемы, но это опять теория!
Пришлось, как обычно, браться за Perl.
Программка в общем несложная, надо только перевести цвет в модель HSV и «вращать» оттенок по кругу. А называется этот приём hue rotation. Но вот найти формулу перевода из одной модели в другую оказалось очень нелёгкой задачей.
Чувствую, кое-кто уже набрал в Яндексе «RGB в HSV», увидел
стопиццоттысяц результатов и удивился: ну как же так? А вот так!
Там есть формула X = C × (1-|h/60 mod 2 -1|)
. И
попробуй догадайся, что h/60 mod 2
— это дробное число
по модулю!
Зато теперь я знаю, что такое цветовой круг и умею генерировать цветовые схемы без регистрации и СМС. А если вдруг это ещё кому-то нужно, то под катом — перловки мешок.
#!/usr/bin/perl use strict; use utf8; use open qw(:std :utf8); use Encode qw(decode); use I18N::Langinfo qw(langinfo CODESET); use v5.10; use List::Util qw( min max ); sub rgb2hsv { my ($r, $g, $b) = @_; my $max = max($r, $g, $b); my $min = min($r, $g, $b); my $h; if($max==$r) { $h = 60*(0+($g-$b)/($max-$min)); } elsif ($max==$g) { $h = 60*(2+($b-$r)/($max-$min)); } elsif ($max==$b) { $h = 60*(4+($r-$g)/($max-$min)); } return ($h, $max==0 ? 0 : ($max-$min)/$max, $max/255); } sub hsv2rgb { my ($h, $s, $v) = @_; my $c = $v*$s; my $a = $h/60; $a -= 2 while($a>=2); my $x = $c*(1-abs($a-1)); my $m = $v-$c; my ($r1, $g1, $b1); if ($h>= 0 && $h< 60) { ($r1, $g1, $b1) = ($c, $x, 0) } elsif ($h>= 60 && $h<120) { ($r1, $g1, $b1) = ($x, $c, 0) } elsif ($h>=120 && $h<180) { ($r1, $g1, $b1) = (0, $c, $x) } elsif ($h>=180 && $h<240) { ($r1, $g1, $b1) = (0, $x, $c) } elsif ($h>=240 && $h<300) { ($r1, $g1, $b1) = ($x, 0, $c) } elsif ($h>=300 && $h<360) { ($r1, $g1, $b1) = ($c, 0, $x) } return(int(0.5+($r1+$m)*255),int(0.5+($g1+$m)*255),int(0.5+($b1+$m)*255)); } sub main { my ($r, $g, $b) = @ARGV; my ($h, $s, $v) = rgb2hsv($r, $g, $b); my $POINTS = 12; for (0..$POINTS-1) { printf ("%d, %d, %d; #%02X%02X%02X\n", $r, $g, $b, $r, $g, $b); printf ("HUE = %.2f, SATURATION = %2.1f%%, VALUE = %.1f%%\n",$h,$s*100,$v*100); $h -= 360/$POINTS; $h += 360 if ($h<0); ($r, $g, $b) = hsv2rgb($h,$s,$v); } } $| = 1; &main;
|
</> |