Плавный спектр для рендеринга Мандельброта

В настоящее время я пишу программу для генерирования действительно огромных (65536x65536 пикселей и выше) изображений Мандельброта, и я хотел бы разработать схему спектра и раскраски, которая бы соответствовала им. Изображение Мандельброта из Википедии кажется отличным примером, особенно то, как палитра остается различной на всех уровнях масштабирования последовательности. Я не уверен, что он вращает палитру или делает какой-то другой трюк для достижения этой цели.

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

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

15.12.2008 19:26:33
7 ОТВЕТОВ

Кажется простым сделать методом проб и ошибок. Предположим, вы можете определить HSV1 и HSV2 (оттенок, насыщенность, значение) цветов конечных точек, которые вы хотите использовать (черный и белый; синий и желтый; темно-красный и светло-зеленый и т. Д.), И предположить, что у вас есть алгоритм для назначения значение P между 0,0 и 1,0 для каждого из ваших пикселей. Тогда цвет этого пикселя становится

(H2 - H1) * P + H1 = HP
(S2 - S1) * P + S1 = SP
(V2 - V1) * P + V1 = VP

После этого просто наблюдайте за результатами и смотрите, как они вам нравятся. Если алгоритм присвоения P является непрерывным, то градиент также должен быть плавным.

4
15.12.2008 20:00:38
Однако я не могу просто гарантировать диапазон значений от 0 до 1,0, так как это приводит к тому, что изображения с более высоким разрешением теряют детализацию (они заканчиваются всеми значениями с высокой итерацией). Необходим какой-то постепенный поворот палитры.
Nick Johnson 16.12.2008 07:36:59
Это нормально. Если диапазон бесконечен по размеру, у него все еще может быть период, даже если этот период наложен на него. Просто выберите соответствующее значение N и отобразите значения для себя mod N, а затем масштабируйте его до диапазона 0-1.
Paul Brinkley 16.12.2008 15:43:42

Используйте алгоритм сглаживания, чтобы рассчитать все значения в области просмотра, а затем сопоставьте свою палитру от минимального до максимального значения. Таким образом, при увеличении масштаба и более высоких значениях больше не видно, палитра также будет уменьшаться. С теми же константами для n и B вы получите диапазон от 0,0 до 1,0 для полностью уменьшенного набора, но при более глубоких масштабах динамический диапазон будет уменьшаться, скажем, от 0,0 до 0,1 при увеличении 200%, от 0,0 до 0,0001 при Зум 20000% и т. Д.

6
16.12.2008 09:22:43
РЕШЕНИЕ

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

4
17.12.2008 10:52:53

Это алгоритм сглаживания цвета:

Допустим, вы начинаете с комплексного числа z0и повторяете nвремя до его выхода. Пусть конечная точка будет zn.

Гладкое значение будет

nsmooth := n + 1 - Math.log(Math.log(zn.abs()))/Math.log(2)

Это работает только для Мандельброта, если вы хотите вычислить гладкую функцию для множеств Джулии, тогда используйте

Complex z = new Complex(x,y);
double smoothcolor = Math.exp(-z.abs());

for(i=0;i<max_iter && z.abs() < 30;i++) {
    z = f(z);
    smoothcolor += Math.exp(-z.abs());
}

Затем smoothcolorнаходится в интервале (0,max_iter).

Разделите smoothcolorс, max_iterчтобы получить значение от 0 до 1.

Чтобы получить плавный цвет из значения:

Это можно назвать, например (на Java):

Color.HSBtoRGB(0.95f + 10 * smoothcolor ,0.6f,1.0f);

поскольку первое значение в цветовых параметрах HSB используется для определения цвета из цветового круга.

34
17.06.2015 18:50:35
Спасибо за плавную цветовую формулу Julia Set, она использовалась в shadertoy.com/view/XssXDr
Erik Martino 7.05.2014 06:02:25
Как конвертировать nsmooth в значение цвета?
vcapra1 20.12.2018 02:20:53
Color.HSBtoRGB (0,95f + 10 * nsmooth, 0,6f, 1,0f); возможно?
Per Alexandersson 20.12.2018 06:20:03

Вот типичный внутренний цикл для наивного генератора Мандельброта. Чтобы получить плавный цвет, вы хотите передать реальные и сложные «длины» и итерацию, на которую вы выпали. Я включил код Мандельброта, чтобы вы могли видеть, какие переменные использовать для вычисления цвета.

for (ix = 0; ix < panelMain.Width; ix++)
    {
    cx = cxMin + (double )ix * pixelWidth;
    // init this go 
    zx = 0.0;
    zy = 0.0;
    zx2 = 0.0;
    zy2 = 0.0;
    for (i = 0; i < iterationMax && ((zx2 + zy2) < er2); i++)
        {
        zy = zx * zy * 2.0 + cy;
        zx = zx2 - zy2 + cx;
        zx2 = zx * zx;
        zy2 = zy * zy;
        }
    if (i == iterationMax)
        {
        // interior, part of set, black
        // set colour to black
        g.FillRectangle(sbBlack, ix, iy, 1, 1);
        }
    else
        {
        // outside, set colour proportional to time/distance it took to converge
        // set colour not black
        SolidBrush sbNeato = new SolidBrush(MapColor(i, zx2, zy2));
        g.FillRectangle(sbNeato, ix, iy, 1, 1);
        }

и MapColor ниже: (см. эту ссылку, чтобы получить функцию ColorFromHSV )

 private Color MapColor(int i, double r, double c)
                {
                double di=(double )i;
                double zn;
                double hue;

                    zn = Math.Sqrt(r + c);
                    hue = di + 1.0 - Math.Log(Math.Log(Math.Abs(zn))) / Math.Log(2.0);  // 2 is escape radius
                    hue = 0.95 + 20.0 * hue; // adjust to make it prettier
                    // the hsv function expects values from 0 to 360
                    while (hue > 360.0)
                        hue -= 360.0;
                    while (hue < 0.0)
                        hue += 360.0;

                    return ColorFromHSV(hue, 0.8, 1.0);
                }

MapColour «сглаживает» значения катапультирования от 0 до 1, которые затем можно использовать для сопоставления цвета без ужасных полос. Игра с MapColour и / или функцией hsv позволяет вам изменять используемые цвета.

5
23.05.2017 12:26:03

здесь вы можете найти версию с javascript

Применение :

var rgbcol = [] ;
var rgbcol = MapColor ( Iteration , Zy2,Zx2 ) ;
point ( ctx , iX, iY ,rgbcol[0],rgbcol[1],rgbcol[2] );  

функция

/*
 * The Mandelbrot Set, in HTML5 canvas and javascript.
 * https://github.com/cslarsen/mandelbrot-js
 *
 * Copyright (C) 2012 Christian Stigen Larsen
*/

/*
 * Convert hue-saturation-value/luminosity to RGB.
 *
 * Input ranges:
 *   H =   [0, 360] (integer degrees)
 *   S = [0.0, 1.0] (float)
 *   V = [0.0, 1.0] (float)
 */
function hsv_to_rgb(h, s, v)
{
  if ( v > 1.0 ) v = 1.0;
  var hp = h/60.0;
  var c = v * s;
  var x = c*(1 - Math.abs((hp % 2) - 1));
  var rgb = [0,0,0];

  if ( 0<=hp && hp<1 ) rgb = [c, x, 0];
  if ( 1<=hp && hp<2 ) rgb = [x, c, 0];
  if ( 2<=hp && hp<3 ) rgb = [0, c, x];
  if ( 3<=hp && hp<4 ) rgb = [0, x, c];
  if ( 4<=hp && hp<5 ) rgb = [x, 0, c];
  if ( 5<=hp && hp<6 ) rgb = [c, 0, x];

  var m = v - c;
  rgb[0] += m;
  rgb[1] += m;
  rgb[2] += m;

  rgb[0] *= 255;
  rgb[1] *= 255;
  rgb[2] *= 255;

  rgb[0] = parseInt ( rgb[0] ); 
  rgb[1] = parseInt ( rgb[1] );
  rgb[2] = parseInt ( rgb[2] );  

  return rgb;
}

// http://stackoverflow.com/questions/369438/smooth-spectrum-for-mandelbrot-set-rendering
// alex russel : http://stackoverflow.com/users/2146829/alex-russell

function MapColor(i,r,c)
{
    var di= i;
    var zn;
    var hue;

        zn = Math.sqrt(r + c);
        hue = di + 1.0 - Math.log(Math.log(Math.abs(zn))) / Math.log(2.0);  // 2 is escape radius
        hue = 0.95 + 20.0 * hue; // adjust to make it prettier
        // the hsv function expects values from 0 to 360
        while (hue > 360.0)
            hue -= 360.0;
        while (hue < 0.0)
            hue += 360.0;

        return hsv_to_rgb(hue, 0.8, 1.0);
}
-1
21.06.2016 10:03:35

Что происходит с цветовым отображением на этом изображении, так это то, что в индексе используется «функция передачи журнала» (согласно документации). Как именно он это делает, я еще не выяснил. Программа, которая его создала, использует палитру из 400 цветов, поэтому диапазон индексов [0,399), при необходимости оборачиваясь. Мне удалось приблизиться к его поведению. Я использую диапазон индекса [0,1) и отображаю его так:

    double value = Math.log(0.021 * (iteration + delta + 60)) + 0.72;
    value = value - Math.floor(value);

Довольно странно, что мне приходится использовать эти специальные константы, чтобы сопоставить результаты, так как я сомневаюсь, что они это делают. Но что работает в конце концов, верно?

0
4.04.2019 17:42:56