В Java сопоставьте видимый спектр с RGB на основе вычисленного целого числа (более высокие значения должны быть ближе к ультрафиолетовому, а более низкие - ближе к инфракрасному)

Это для рендеринга набора Мандельброта (см. https://en.wikipedia.org/wiki/Mandelbrot_set); цвет каждой точки должен основываться на количестве итераций, которые потребовались комплексному числу Z, чтобы выйти из набора.

Я хотел бы сопоставить цвета так, чтобы, если точка является элементом набора Мандельброта, она должна быть чисто красной [RGB (255, 0, 0), 0% по спектру от ИК до УФ].

Если расчет был остановлен из-за того, что цикл достиг предела итераций, цвет должен быть чисто фиолетовым [RGB (249, 192, 255), 100% по спектру].

Я предполагаю, что решение включает в себя что-то вроде:

//where iterCount is the value for that point, maxIters is the iteration cap
double spectrumValue=iterCount/maxIters; //percent in decimal form
setColor(RGBConversion(spectrumValue));

Однако то, что я не знаю, - это метод RGBConversion. В идеале он должен работать в постоянное время.


person Mat Jones    schedule 20.11.2015    source источник
comment
Разве простой if оператор, проверяющий, равно ли iterCount maxIters, не дает вам возможность указать два разных цвета?   -  person Kenney    schedule 20.11.2015
comment
Градиент итерации не является равномерным, он становится круче, приближаясь к M-Set. Таким образом, при равномерном цветовом градиенте будет отображаться очень мало пикселей максимального цвета, и вы можете учитывать это при создании array[maxiters]. Мой метод заключался в том, чтобы создать array[256] градуированных цветов, которые плавно переходят при индексировании как array[iterations % 256]. Но также учтите, что итерации рядом с M-Set довольно хаотичны, ваш одноцветный градиент, вероятно, будет выглядеть лучше, чем мой метод, где я заставил соседние пиксели, имеющие очень разные итерации, быть средне-серыми (сам M-Set черный).   -  person Weather Vane    schedule 20.11.2015
comment
@Kenney: да, но это дает мне только 2 цвета, тогда как мне нужен градиент между ними, который включает сотни или, может быть, тысячи цветов.   -  person Mat Jones    schedule 20.11.2015
comment
@WeatherVane, не могли бы вы пояснить, что вы имеете в виду? Я предполагаю, что вы хотите сохранить цвета в массиве [256], но A, мне нужно больше цветов, и B, чего достигаются итерации индекса% 256?   -  person Mat Jones    schedule 20.11.2015
comment
@ mjones.udri Я имею в виду, что мои цвета переносятся, поэтому, если итераций 256, цвет будет из array[0], цвета повторяются каждые 256 итераций. Я погас синий - ›зеленый (без красного), затем зеленый -› красный (без синего), а затем красный - ›синий (без зеленого) в массиве 256, на самом деле 255, я думаю (3 * 85).   -  person Weather Vane    schedule 20.11.2015
comment
тысячи цветов, которые будут маловероятными, если вы переходите от одного цвета к другому. Цветовое разрешение каждого компонента в устройстве составляет всего 256, поэтому единственный способ получить тысячи цветов будет выглядеть беспорядочно.   -  person Weather Vane    schedule 20.11.2015


Ответы (2)


Вы должны использовать цветовое пространство «HSL» или «HSB» (также известное как «HSV»), где «H» в обоих случаях означает «оттенок». Оттенок обычно измеряется как угол в градусах, где 0 градусов представляет красный цвет, 120 - зеленый, 240 - синий, хотя некоторые библиотеки используют диапазон 0..1.

Сохранение постоянных «S» и «B» и линейное изменение «H» от нижнего края диапазона к верхнему приведет к получению типичной «радуги» цветов.

В вашем случае, поскольку вы используете Java и AWT, вы можете просто позвонить:

setColor(Color.getHSBColor(spectrumValue, 1.0, 1.0));
person Alnitak    schedule 20.11.2015
comment
О, хорошее предложение. Похоже, этот ответ помогает: stackoverflow.com/questions/2997656/ - person bcholmes; 20.11.2015
comment
@bcholmes, строго говоря, ваш ответ делает то же самое, но хорошо работает только для полностью насыщенных цветов. В ваш метод важно включить третичные цвета (например, оранжевый), иначе интерполяция от красного к зеленому пропустит их. - person Alnitak; 20.11.2015
comment
Я пробовал решение, подобное тому, что указано в ссылке, опубликованной @bcholmes, но у меня просто сплошной красный квадрат; Я знаю, что проблема в раскраске, потому что у меня была программа, генерирующая точный рендеринг с другими произвольными схемами цветовой карты. - person Mat Jones; 20.11.2015
comment
@Alnitak да, я использую Java AWT Color. Я также использую Java AWT Graphics, если это актуально. - person Mat Jones; 20.11.2015
comment
Хорошо, просто позвони Color.getHSBColor(spectrumValue, 1.0, 1.0) - person Alnitak; 20.11.2015
comment
@Alnitak Я пробовал это, и он просто сделал каждую точку полностью красной (RGB: 255, 0, 0) - person Mat Jones; 20.11.2015
comment
@ mjones.udri, поэтому вам нужно подтвердить диапазон ваших spectrumValue чисел - они должны быть в диапазоне 0..1 - см. docs.oracle.com/javase/7/docs/api/java/awt/ - person Alnitak; 20.11.2015
comment
SpectrumValue ‹= 1 для всех обстоятельств, потому что iterCount‹ = maxIters; если iterCount достигает maxIters, я отключаю расчет. - person Mat Jones; 20.11.2015
comment
Для вычисления spectrumValue вам может потребоваться преобразовать iterCount и maxIters в числа типа double или float в вашей математике. Если они целые числа, вы всегда получите целочисленный результат. - person bcholmes; 20.11.2015

Вы можете начать с набора цветов, которые представляют ключевые точки спектра: красный, оранжевый, желтый, зеленый, синий, фиолетовый. Скажем, они расположены на равном расстоянии от 0, 0,2, 0,4, 0,6, 0,8 и 1. Затем используйте этот ответ для плавного перехода между ними.

Для каждого интервала вам нужно сопоставить диапазон дельты - от 0,0 до 0,2 - с соотношением 0: 1.

person bcholmes    schedule 20.11.2015