pechkin: (Default)
pechkin ([personal profile] pechkin) wrote2006-02-19 02:30 pm
Entry tags:

К алгоритму раскраски слов

Для каждой буквы слова слева направо высчитать ее расстояния от R, G, B (C, M, Y, K) -- цвет буквы (как?) Эти цифры поделить на порядковый номер буквы в слове, умножить на поправочный коэффициент и прибавить к RGB слова.

RGB буквы можно высчитать из номера буквы, поделив все цветовое пространство на количество букв -- тогда каждой букве попадет свой цвет.

Негативный бэкграунд неплохо выходит по формуле (color + 0x777777) % 0xFFFFFF. Возможно, есть лучшие способы, но этот быстр и дает приемлемый результат.

Update: Не работает, и вот почему: нужно, чтобы последовательность прибавочных коэффициентов была строго убывающей. А она не. Потому что разница между коэффициентами для букв i и i+1 может быть гораздо больше, чем то, на что я их делю. То есть, вот такой вот скрипт:

my @letters = ('_', 'A' .. 'Z', 'a' .. 'z', '0' .. '9');
my $step = 0xFFFFFF / scalar(@letters);
my $start = 0;
my %letter_color = map({$_ => $start += $step} sort(@letters));

foreach (sort(@words))
{
    my $word = $_;
    my $wordcolor = 0;
    
    for (my $i = 0; $i < length($word); $i++)
    {
	my $letter = substr($word, $i, 1);
	my $color = ;
	if (!defined($color))
	{
	    print("Not found color for letter <$letter>!\n");
	}
	else
	{
	    #Each next step should be smaller than the previous
	    my $step = $letter_color{$letter} / ($i + 1);
	    $wordcolor += $step;
	}
    }
}


не дает строго убывающей последовательности, если распечатывать для каждого слова $step, потому что разница между $letter_color{'0'} и $letter_color{'z'} слишком большая. Надо как-то привязаться к этой разнице, а как -- что-то не соображу.

[identity profile] agaspher.livejournal.com 2006-02-19 12:03 pm (UTC)(link)
Красиво.

[identity profile] bigturtle.livejournal.com 2006-02-19 06:40 pm (UTC)(link)
А че красивого-то кроме того, что серый цвет остается серым при преобразовании по последней формуле?

[identity profile] pechkin.livejournal.com 2006-02-20 06:57 am (UTC)(link)
Я видимо зря не объяснил задачу. Есть некоторое количество слов, многие из которых различаются только суффиксами (окончаниями, в смысле, а начала у них одинаковые). Нужно, чтобы при раскраске слова с похожими началами получали похожие цвета, а сильно различающиеся сильно различались бы и по цвету. А уж какие это будут цвета, это уж ладно, не Ван-Гоги горшки обжигают.

[identity profile] bigturtle.livejournal.com 2006-02-19 06:50 pm (UTC)(link)
Даже не всякий серый, а именно вида NN,NN,NN.

[identity profile] pechkin.livejournal.com 2006-02-20 06:58 am (UTC)(link)
А проблема нахождения негатива (я как-то с большим удивлением обнаружил, что это действительно проблема) -- это проблема совсем другая. Даже и не негатив нужен, естественно, а что-то контрастное, чтобы любой цвет был виден на экране.

[identity profile] bigturtle.livejournal.com 2006-02-20 01:55 pm (UTC)(link)
Ну, побитовой инверсией проблема действительно не решается, типа 0x7F7F7F с 0x808080 - плохая комбинация.
Я не о том. Числа вида NNNNNN при этом преобразовании дают красивый цикл:

0-777777-EEEEEE-666666-DDDDDD-555555-CCCCCC-444444-
BBBBBB-333333-AAAAAA-222222-999999-111111-888888

Только 0xFFFFFF->0x777777 выпадает.

(Anonymous) 2006-02-19 10:23 pm (UTC)(link)
RGB не самая лучшая цветовая модель для этих целей, даже LAB чуть лучше, более ориентирован на восприятие. Но самая хорошая - модель Munsell'a, см. http://www.triplecode.com/munsell/ и далее.

[identity profile] pechkin.livejournal.com 2006-04-03 07:27 am (UTC)(link)
Не работает, и вот почему: нужно, чтобы последовательность прибавочных коэффициентов была строго убывающей. А она не. Потому что разница между коэффициентами для букв i и i+1 может быть гораздо больше, чем то, на что я их делю. То есть, вот такой вот скрипт:

my @letters = ('_', 'A' .. 'Z', 'a' .. 'z', '0' .. '9');
my $step = 0xFFFFFF / scalar(@letters);
my $start = 0;
my %letter_color = map({$_ => $start += $step} sort(@letters));

foreach (sort(@words))
{
    my $word = $_;
    my $wordcolor = 0;
    
    for (my $i = 0; $i < length($word); $i++)
    {
	my $letter = substr($word, $i, 1);
	my $color = ;
	if (!defined($color))
	{
	    print("Not found color for letter <$letter>!\n");
	}
	else
	{
	    #Each next step should be smaller than the previous
	    my $step = $letter_color{$letter} / ($i + 1);
	    $wordcolor += $step;
	}
    }
}


не дает строго убывающей последовательности, если распечатывать для каждого слова $step, потому что разница между $letter_color{'0'} и $letter_color{'z'} слишком большая. Надо как-то привязаться к этой разнице, а как -- что-то не соображу.