2012-06-20 4 views
37

Есть ли наилучшая практика о том, как хэш произвольной строки в значение цвета RGB? Или быть более общим: до 3 байт.Хэш-строка в цвет RGB

Вы спрашиваете: когда мне это понадобится? Для меня это не имеет значения, но представьте эти диаграммы на любом GitHub network page. Там вы можете увидеть что-то вроде этого:

git branches

Где каждый цвет линии означает отчетливую GIT ветвь. Низкотехнологичный подход для окраски этих ветвей был бы CLUT (таблица цветового поиска). Более сложная версия будет:

$branchColor = hashStringToColor(concat($username,$branchname)); 

Потому что вы хотите статический цвет каждый раз, когда видите представление ветвей. И для бонусных очков: как вы обеспечиваете равномерное распределение цветов этой хэш-функции?

Таким образом, ответ на мой вопрос сводится к реализации hashStringToColor().

ответ

26

Хорошая хеш-функция обеспечит почти равномерное распределение по ключевому пространству. Это уменьшает вопрос о том, как преобразовать случайное 32-разрядное число в 3-байтное пространство RGB. Я не вижу ничего плохого в том, что просто беру минимум 3 байта.

int hash = string.getHashCode(); 
int r = (hash & 0xFF0000) >> 16; 
int g = (hash & 0x00FF00) >> 8; 
int b = hash & 0x0000FF; 
+0

Работал отлично, спасибо. – clayzermk1

+9

Хотя если вы хотите обеспечить читаемые цвета (например, обеспечить достаточно высокий контраст и насыщенность), вам придется немного поработать над этим. Может быть проще работать в HSV или LAB и конвертировать в RGB. – naught101

+0

Прекрасное решение! –

2

В качестве примера, this is how Java calculates the hashcode of a string (строка 1494 и далее). Он возвращает int. Затем вы можете рассчитать по модулю int с 16 777 216 (2^24 = 3 байта), чтобы получить номер «RGB-совместимый».

Это детерминированный расчет, поэтому одно и то же слово (ы) всегда будет иметь один и тот же цвет. Вероятность столкновения хешей (2 строки одного цвета) мала. Не уверен в распределении цветов, но, вероятно, довольно случайный.

+0

Я думаю, что хэш столкновения можно пренебречь, так как, когда происходит столкновение, что это не столько вопрос до тех пор, пока вы не должны соседям цветов (как в примере данный), чтобы отличаться. –

+1

Случайность распределения цветов может быть эстетической проблемой. Есть много «уродливых» цветов, может быть, практическая идея применить какой-то вес к компонентам, чтобы попытаться улучшить красивое: уродливое отношение. :) – Wug

19

Для всех пользователей Javascript там, я совместил принятый ответ от @ джеф-неродного с функцией djb2 хэша от erlycoder.

В результате на вопрос:

function djb2(str){ 
    var hash = 5381; 
    for (var i = 0; i < str.length; i++) { 
    hash = ((hash << 5) + hash) + str.charCodeAt(i); /* hash * 33 + c */ 
    } 
    return hash; 
} 

function hashStringToColor(str) { 
    var hash = djb2(str); 
    var r = (hash & 0xFF0000) >> 16; 
    var g = (hash & 0x00FF00) >> 8; 
    var b = hash & 0x0000FF; 
    return "#" + ("0" + r.toString(16)).substr(-2) + ("0" + g.toString(16)).substr(-2) + ("0" + b.toString(16)).substr(-2); 
} 

UPDATE: Исправлена ​​возвращенная строка всегда возвращает # 000000 формат шестнадцатеричной строки на основе редактирования по @alexc (спасибо!).

+3

Вы также можете форматировать цвет следующим образом: return "rgb (" + r + "," + g + "," + b + ")" –

+1

@StuGla: Я не могу вспомнить, был ли шестнадцатеричный формат частью требования; Читая его сейчас, похоже, это не так. Поскольку вопрос задавался в целом, я думаю, что автора больше интересует алгоритм хеширования, чем формат цветовой строки. Однако, если контекст вопроса - CSS, то ваш гораздо более чистый способ сделать это. Привет, дружище, спасибо! – clayzermk1

+0

@StuGla: Это позволяет также добавлять прозрачность. – MastaBaba

8

Я пробовал все остальные решения, но обнаружил, что подобные строки (string1 vs string2) создают цвета, которые слишком похожи по моему вкусу. Поэтому я построил свое влияние под влиянием вклада и идей других.

Этот номер будет вычислять контрольную сумму MD5 для строки и принимать первые 6 шестнадцатеричных цифр для определения 24-битного кода RGB.

Функциональность MD5 является открытым исходным кодом JQuery подключить Функция JS идет следующим образом:.

function getRGB(str){ 
    var hash = $.md5(str); 
    var rgb = '#' + hash.substring(0,2) + hash.substring(2,4) + hash.substring(4,6); 
    return rgb; 
} 

Ссылка на этот рабочий пример на jsFiddle. Просто введите строку в поле ввода и нажмите enter, и делайте это снова и снова, чтобы сравнить ваши результаты.

+0

Вы можете упростить строку 3 до: 'var rgb = '#' + hash.substring (0,6);' –

+0

* Я попробовал все другие решения, предоставленные другими пользователями (...) * Нет, вы не сделали этого :), как ответ Джеффа Фостера описывает семейство с ** бесконечным ** многими решениями. Ваше решение является членом этого семейства, кстати. –

Смежные вопросы