Logo by reallybigname - Contribute your own Logo!

END OF AN ERA, FRACTALFORUMS.COM IS CONTINUED ON FRACTALFORUMS.ORG

it was a great time but no longer maintainable by c.Kleinhuis contact him for any data retrieval,
thanks and see you perhaps in 10 years again

this forum will stay online for reference
News: Follow us on Twitter
 
*
Welcome, Guest. Please login or register. March 28, 2024, 01:20:52 PM


Login with username, password and session length


The All New FractalForums is now in Public Beta Testing! Visit FractalForums.org and check it out!


Pages: [1]   Go Down
  Print  
Share this topic on DiggShare this topic on FacebookShare this topic on GoogleShare this topic on RedditShare this topic on StumbleUponShare this topic on Twitter
Author Topic: Julia smooth-colouring : how to do ?  (Read 16515 times)
0 Members and 1 Guest are viewing this topic.
Matplotlib
Forums Freshman
**
Posts: 13



WWW
« on: April 24, 2017, 01:00:04 PM »

Hello,

I am running a Julia set program, and I have some issues... I don't want to enter in the language's details, it's not what's wrong.
I run z\mapsto z^2+c several times, till I escape or I get to the max number of iterations possible. During the process, I sum over all the exp(-|z|) values (is it the good way for smooth-colouring ?), that I store in a var (let's name it "escape_count"). In the end, I get a number that I don't know how to use ! How to get a color from the value of escape_count ?

Any examples with explanations would be very helpful, even if you redirect to some papers ! (I haven't been able to find something clear about the smooth-colouring)
Logged

lycium
Fractal Supremo
*****
Posts: 1158



WWW
« Reply #1 on: April 24, 2017, 04:16:03 PM »

Welcome to the forum smiley Some resources I've found on this topic a few years ago:

http://www.iquilezles.org/www/articles/mset_smooth/mset_smooth.htm
http://linas.org/art-gallery/escape/escape.html

Also there is even a master's thesis on this topic by Jussi Härkönen: http://jussiharkonen.com/gallery/coloring-techniques/
Logged

xenodreambuie
Conqueror
*******
Posts: 124



WWW
« Reply #2 on: April 24, 2017, 10:09:12 PM »

That is said to be a good smooth colouring method, though I haven't tried it. The most general way to map a scalar to colours is to multiply it by a strength (or density) parameter and add an offset parameter. Then wrap it into a fixed range as an index into a gradient. The alternative is to generate colour values algorithmically, typically to make some kind of endlessly varying combination of waves.
Logged

Regards, Garth
http://xenodream.com
FractalStefan
Explorer
****
Posts: 45



WWW
« Reply #3 on: April 24, 2017, 11:52:31 PM »

Hi Matplotlib,

in your Iterate function, where you do the Z->Z²+C iteration, just do the following before you return the iterator value (it):

Code:
it = it + 2 - log(log(a² + b²)) / log(2)

it is the iterator value, and a and b are the real and imaginary part of Z after Z escaped to infinity.

For maximum speed, you can define log(2) as a constant.

Your color mapping code should of course be able to cope with a fractional iterator value.

The escape radius should be greater than the usual 2, e.g. 4 or 5, to get best results.

Example script (Mandelbrot, but should also work for Julia since they both use the same iteration equation). Click the checkbox to see the difference.

Stefan
Logged
lycium
Fractal Supremo
*****
Posts: 1158



WWW
« Reply #4 on: April 24, 2017, 11:57:08 PM »

For maximum speed, you can define log(2) as a constant.

Pretty sure maximum speed requires 1/log(2), not log(2) wink

Furthermore pretty much every compiler will precompute log(2), but won't do the 1/log(2) optimisation.
Logged

FractalStefan
Explorer
****
Posts: 45



WWW
« Reply #5 on: April 25, 2017, 12:25:35 AM »

Pretty sure maximum speed requires 1/log(2), not log(2) wink

Because multiplying is faster than dividing?

I made a quick test in JavaScript. The result:

Division: 1204 ms
Multiplication: 1203 ms

Really a big difference! ;-)

Edit: But you're right - at least in JavaScript there's no difference if log(2) is defined as constant or used directly as operand:

Quote
Using a constant as operand

Division: 1205 ms
Multiplication: 1202 ms

Using log(2) as operand

Division: 1203 ms
Multiplication: 1204 ms

Edit2: Okay, I was wrong, multiplication is faster than division. JavaScript tricked me as it optimized the testing loop. Apparently it saw that I did nothing with the result, so I changed the script (here's version 2) so that it now outputs the results - and indeed, the diffrences are now significant:

Quote
Using a constant as operand

Division: 19465 ms (result: 721337883.3478911)
Multiplication: 13629 ms (result: 721369432.0115957)

Using log(2) as operand

Division: 20261 ms (result: 721312455.102812)
Multiplication: 13846 ms (result: 721337110.8961784)

So big difference between mul and div, but not between using log(2) as a constat or directly... roll eyes

Edit2: Wow, Opera and Chrome are really slow compared to Firefox which I used for the above results!

Opera:

Quote
Using a constant as operand

Division: 32267 ms (result: 721345943.255802)
Multiplication: 29262 ms (result: 721320344.2994019)

Using log(2) as operand

Division: 31125 ms (result: 721339741.0393113)
Multiplication: 28634 ms (result: 721362340.1294624)

Chrome:

Quote
Using a constant as operand

Division: 28945 ms (result: 721352593.7384236)
Multiplication: 26304 ms (result: 721348815.09295)

Using log(2) as operand

Division: 28062 ms (result: 721325577.7421819)
Multiplication: 26247 ms (result: 721343337.9390984)
« Last Edit: April 25, 2017, 01:26:25 AM by FractalStefan » Logged
lycium
Fractal Supremo
*****
Posts: 1158



WWW
« Reply #6 on: April 25, 2017, 06:27:16 AM »

lol, "performance" testing with JavaScript cheesy

You have two "Edit2" btw wink
Logged

Matplotlib
Forums Freshman
**
Posts: 13



WWW
« Reply #7 on: April 26, 2017, 09:13:18 PM »

@lycium the PhD is just amazing ! Explains everything in details ! In fact, I had already been on the other links you gave to me, and I did not quite understand properly what they wanted to do.

@FractalStefan thanks ! Also, thanks for the speed comparisons ! I never thought to store 1/ln(2) in a var, which appears to be a simple but great idea (and yes, I use ln for log_e !)
Logged

Matplotlib
Forums Freshman
**
Posts: 13



WWW
« Reply #8 on: May 10, 2017, 05:42:40 PM »

Okay ! I've read that PhD, it's just as great as I expected ! I looove when things are detailed and as clear as mountain water !

Hence, I've generated by myself some images :
+ http://matplotlib.deviantart.com/art/Julia-set-SIC-algorithm-c-0-5-0-25i-679827575
+ http://matplotlib.deviantart.com/art/Julia-set-SIC-algorithm-c-0-75-0-11i-679827809?ga_submit_new=10%3A1494428357
+ http://matplotlib.deviantart.com/art/Julia-set-SIC-algorithm-c-0-4-0-6i-679829631?ga_submit_new=10%3A1494429324
Let me copy/paste the info I gave on the images' page :
Smooth iteration count : u(z0)=n+1+logd{ln(M)/ln|zn|} where n is the number of iterations, M the maximum radius bound, and d the degree of equation : zn+1=aznd+Q(zn) where deg(Q)<=d-1

Now, the palette I use is defined as follows :
+ r=⌊u(z0)/nmax
+ g,b = r,r

This means I have a palette that has length 256, and palette[i]=i for i∈[|0,255|]. But here are some issues I get :
+ u(z0) appears to never reach nmax. Therefore, I never get r greater than a bouded value (usually around 150). What is the maximum bound of this function u I'm using ? I have tried using the famous u(z0)=n+1-logd{|zn|}, but this does not change much the values taken.
+ How to use an adapted coloured palette ? It looks like the values taken by u get stuck on one side of the palette, that side depending on the current fractal. I have no clue of how to generate beautiful images using all the colours on the palette. Instead, it only uses half the palette.

Here's a palette I'm using (.python/numpy code) :
Code:
palette_r = list(map(lambda z: int(z),np.linspace(0,90,538).tolist() +np.linspace(90,251,428).tolist() +np.linspace(251,251,544).tolist()+np.linspace(251,130,542).tolist()))
palette_g = list(map(lambda z: int(z),np.linspace(0,233,538).tolist()+np.linspace(233,222,428).tolist()+np.linspace(222,0,544).tolist()  +np.linspace(0,0,542).tolist()))
palette_b = list(map(lambda z: int(z),np.linspace(140,0,538).tolist()+np.linspace(0,2,428).tolist()    +np.linspace(2,4,544).tolist()    +np.linspace(4,127,542).tolist()))
It looks like this :


Now, let's generate the Julia set for the value c=0.5+0.25i using this palette (smaller size) :


I'm basically calling palette_X[I] for I=⌊L*u/nmax⌋ where L=len(palette_X). As you can notice, the render is not that good, as a lot of the image is coloured blue.
Also, another issue is that sometimes, u/nmax can exceed 1, so I have an "out of range" error raised. That can be easily fixed by having the palette looping itself and using a modulo, but I just don't get why it behaves like this, as I noticed that u never reached values higher than nmax (I had no problems using the B&W palette).
Logged

FractalStefan
Explorer
****
Posts: 45



WWW
« Reply #9 on: May 14, 2017, 12:59:08 AM »

In order to see more of the palette colors, you can use a nonlinear function to stretch the colors at the higher end of the iteration count and compress them at the lower end.
In -> this thread I described some formulas for this purpose.
Logged
Matplotlib
Forums Freshman
**
Posts: 13



WWW
« Reply #10 on: May 15, 2017, 08:18:59 PM »

Okay, I'm now using the hyperbolic tangent as a non-linear index for the palette. I also noticed I need a "smooth palette", which the linear interpolation does not provide. I'm now using a Bezier interpolation, and I got this render : http://matplotlib.deviantart.com/art/Julia-set-SIC-algorithm-c-0-4-0-6i-680773601 (details in description)

Most of my issues are now solved, thanks !
Logged

FractalStefan
Explorer
****
Posts: 45



WWW
« Reply #11 on: May 15, 2017, 09:11:44 PM »

Okay, I'm now using the hyperbolic tangent as a non-linear index for the palette.

Interesting idea - I have to try this, too! smiley

However - since tanh(x) only approximates the value of 1, you should use

i = tanh(n * u/Nmax) / tanh(n)

with n = ]0,10] (for example 0.1 ... 10)

Also, if you set n by a slider control (or some other input control), the user can set the linearity of the gradient individually.

I also noticed I need a "smooth palette", which the linear interpolation does not provide. I'm now using a Bezier interpolation, and I got this render : http://matplotlib.deviantart.com/art/Julia-set-SIC-algorithm-c-0-4-0-6i-680773601 (details in description)

Nice! Can you explain this more detailed (Bezier interpolation)?
Logged
Matplotlib
Forums Freshman
**
Posts: 13



WWW
« Reply #12 on: May 15, 2017, 10:10:20 PM »

Nice! Can you explain this more detailed (Bezier interpolation)?
I'll make a more detailed thread tomorrow with the the computer as I already thought about creating one smiley
Logged

FractalStefan
Explorer
****
Posts: 45



WWW
« Reply #13 on: May 16, 2017, 01:18:34 AM »

I'll make a more detailed thread tomorrow with the the computer as I already thought about creating one smiley

Very good! smiley

And I tried the hyperbolic tangent function meanwhile. The results are included in the comparision chart in my new article about color mapping methods:

http://www.stefanbion.de/fraktal-generator/colormapping/

BTW: I don't use a predefined color palette; instead the actual colors are calculated dynamically by interpolation. For example, if color 1 is #008000 and color 2 is #FF0080, then with a normalized color index of 0.5, the resulting color will be #7F4040. This way the colors automatically become smoothed (when using a fractional iteration count) . Is this similar to what you are doing, except that you are using this Bezier thing instead of linear interpolation as I do?
Logged
Matplotlib
Forums Freshman
**
Posts: 13



WWW
« Reply #14 on: May 16, 2017, 11:58:55 AM »

You won't believe it but the color-mapping I prefer amongst all the ones you tried is the tanh smiley

Anyways, here's what we talked about yesterday evening : http://www.fractalforums.com/programming/creating-a-good-palette-using-bezier-interpolation/
Logged

Pages: [1]   Go Down
  Print  
 
Jump to:  

Related Topics
Subject Started by Replies Views Last post
Smooth colouring of convergent fractals Programming zenzero-2001 13 7342 Last post July 21, 2011, 01:10:47 AM
by zenzero-2001
Colouring Mandelbulb 3d paolo 4 2253 Last post July 13, 2011, 07:53:32 PM
by Madman
Direct logarithmic colouring (new) Theories & Research Alef 2 578 Last post April 24, 2012, 06:17:50 PM
by Alef
Undo colouring bug bug reporting Madman 4 10591 Last post March 25, 2013, 10:00:35 PM
by Jesse
Sinclair BASIC Mandelbrot smooth colouring Help & Support simon.snake 11 879 Last post October 15, 2016, 05:11:20 PM
by simon.snake

Powered by MySQL Powered by PHP Powered by SMF 1.1.21 | SMF © 2015, Simple Machines

Valid XHTML 1.0! Valid CSS! Dilber MC Theme by HarzeM
Page created in 0.195 seconds with 24 queries. (Pretty URLs adds 0.013s, 2q)