Title: Creating a good palette using Bezier interpolation Post by: Matplotlib on May 16, 2017, 11:56:59 AM In order to define a palette, one can define some control points, and use linear interpolation to create a gradient. This is what every drawing software does. But when setting up multiple control points, it can resul in some "spikes", and the fractal rendered using this palette can be a bit rough. A way to do so is to preserve differentiability more than continuity. This results in this image :
(https://img4.hostingpics.net/pics/687928smoothness.png) Fig. 1 : Left, C0 interpolation ; right : C1 interpolation How to create such a palette ? First, let's take the example of my palette, composed as three lists palette_r, palette_g and palette_b, all of length 2052. Plot the control points : on the x axis, plot the index of the point in the list, and on the y axis, the RGB value. To make things clear, a linear interpolation would look like this : (https://img4.hostingpics.net/pics/432440lininterp.png) Fig. 2 : Linear interpolation for all three RGB values We'll use a Bezier interpolation (cubic splines) to be able to keep the differientiability at the control points. By setting up control points, one can achieve a cubic spline : given 4 control points P1, P2, P3 and P4, we can define the cubic spline by B(t)=t3P1+3t²(1-t)P2+3t(1-t)²P3+(1-t)3P4 (this uses the Bernstein polynomials ; I won't explain the whole theory here, but it is really interesting, and you should check the Wikipedia articles to give it a start). (https://img4.hostingpics.net/pics/355903cubicsplines.png) Fig. 3 : Cubic splines for the R palette Given a palette point B, C or D (notations of the Figure 3), if one lines up the previous and the next control points with the palette point, then the differentiability is provided (one the several properties of the Bezier spline is that the vectors P1P3 and P3P4 are tangent to the curve). Ajusting the different control points, and doing so for the three palette lists results in this : (https://img4.hostingpics.net/pics/781609bezierinterpolate.png) Fig. 4 : The results for the three palettes. It is clear that the linear interpolation gives "spikes" due to roughness around the palette control points. The "steps" for the cubic splines are because colours as defined with three integer values, and not continuous ones At last, we can compare the results with the palette itself : (http://orig01.deviantart.net/add2/f/2017/136/f/6/palette_using_bezier_interpolation_by_matplotlib-db9bcu6.png) Fig. 5 : Comparison of the results Title: Re: Creating a good palette using Bezier interpolation Post by: FractalStefan on May 16, 2017, 01:22:38 PM Excellent results - but I wonder how the control points for the Bezier calculation are defined. Are you (or the user) doing this manually, or is this done by an algorithm? Can this be done automatically at all?
I tried something similar recently - but instead of Bezier I used a sinus shape so connect the palette points: (http://666kb.com/i/dj9hvf3n2fx2v7168.png) (freehand sketch :)) The results were better than linear interpolation, but not really satisfying... Title: Re: Creating a good palette using Bezier interpolation Post by: Matplotlib on May 16, 2017, 01:51:35 PM I did this all by hand, but yes, there is a way to do this fully automatically. I already spent a whole afternoon on this, I just didn't want this to become spending the whole week :)
If I get bored, I'll program an app that will allow the user to define the control points, and that will automatically compute the palette. Well, doesn't this already exist ? Title: Re: Creating a good palette using Bezier interpolation Post by: SamTiba on May 16, 2017, 06:35:56 PM Didn't thought the implementation of that is new.
I'm using cubic spline interpolation on Matlab for a while now, don't have the time right now but I can compare the results later if it's the same or almost the sa,e. Title: Re: Creating a good palette using Bezier interpolation Post by: FractalStefan on May 16, 2017, 07:21:02 PM For comparison, this is a result of sinus-shaped interpolation against linear interpolation as mentioned above:
Linear interpolation: (http://www.stefanbion.de/tmp/mandel_linear_interpolation.png) Sinus-shaped interpolation: (http://www.stefanbion.de/tmp/mandel_sinus_interpolation.png) The function I used is: function GetColorValue(colorStart, colorEnd, colorIndex) { if(colorStart != colorEnd) colorIndex = (Math.sin(colorIndex * Math.PI - Math.PI / 2) + 1) / 2; return ~~(colorStart + (colorEnd - colorStart) * colorIndex); } Where colorStart is the starting value of the color (e.g. 0), colorEnd is the ending value of the color (e.g. 255), and colorIndex is a value from 0 to 1 which points into the color palette which goes from colorStart to colorEnd. (Code is JavaScript.) The reason why I'm not fully satisfied with this method is that the image sometimes looks like "washed out". So this should be an option which can be switched on or off by the user. Edit 1: Instead of colorIndex = (Math.sin(colorIndex * Math.PI - Math.PI / 2) + 1) / 2; this also works: colorIndex = (Math.cos(colorIndex * Math.PI + Math.PI) + 1) / 2; Title: Re: Creating a good palette using Bezier interpolation Post by: Matplotlib on May 19, 2017, 08:57:50 PM I'm using variations on the non-linear color mapping process. Instead of using tanh(n*u/Nmax) (n is adjusted according to the situation), I also tried things like tanh(n*u/Nmax)k where k ranges from 0.5 to 2. At last, I also tried tanh({n*u/Nmax}k) where k ranges from 1 to 2. I used this method to generate new images (some are now in 4K resolution) :
+ http://matplotlib.deviantart.com/art/Julia-set-c-0-763069-0-094691i-681324374 + http://matplotlib.deviantart.com/art/Julia-set-c-1-769382-0-003138i-4K-render-681421802 + http://matplotlib.deviantart.com/art/Yet-another-4K-Julia-set-render-681474369 Title: Re: Creating a good palette using Bezier interpolation Post by: FractalStefan on May 19, 2017, 09:23:41 PM Interesting, but I still wonder (http://www.fractalforums.com/programming/julia-smooth-colouring-how-to-do/msg101623/#msg101623) why you don't use a divisor like tanh(n) in order to yield a result of exaxtly 1 for u == Nmax. |