Reptillian Posted July 9, 2021 Posted July 9, 2021 (edited) I might or might not finish this though. I'm working on Markus-Lyapunov as a C# plugin. If I decide not to finish it up, then I'll be leaving this for others to complete. Random option is just a gradient of random color, and double palettes there mean two gradients. Spoiler // Name: Markus-Lyapunov Fractal // Submenu: Render // Author: Reptorian // Title: Markus-Lyapunov Fractal // Version: .5 // Desc: Generates Markus-Lyapunov Fractal // Keywords: Fractal // URL: https://forums.getpaint.net/profile/85868-reptillian/?ct=1626304395 // Help: #region UICode TextboxControl str_var = "ab"; // [255] ABC-String IntSliderControl abc_repeats = 50; // [1,100] ABC-String Repeats DoubleSliderControl view_size = 100; // [0.1,100] View Size (%) PanSliderControl view_pos = Pair.Create(0.000, 0.000); // View Position DoubleSliderControl c_pos = 0; // [-1,1] C Position ListBoxControl output_mode = 1; // Mode|Default|Duotone CheckboxControl revert_mode = false; // Reverted Mode ColorWheelControl color_a = ColorBgra.FromBgr(255, 0, 0); // [Blue] Color A ColorWheelControl color_b = ColorBgra.FromBgr(0, 255, 255); // [Yellow] Color B #endregion #if DEBUG #endif int[] i_var; int s_str_var; bool validity; double[,] Lyapunov_Surface; double iM; double im; double hpi = Math.PI*2; /* The C# code below is to use for randomized palette mode. Only kept it here for future development. double[] hue; double[] saturation; double[] intensity; */ double contrast(double a){ double b=a*Math.PI-hpi; return .5*(a*a)+.5*(Math.Sin(b)+1)/2; } /* The C# code below is to use for randomized palette mode. Only kept it here for future development. double rescale(double a,double b){ double i = a + b ; return i * 765; } ColorBgra RGB_from_HSI(double hue, double saturation, double intensity){ int H = ((int)(hue)/60)%6; int Z = 1 - Math.Abs((H%2)-1); double C = intensity * saturation / (1 + (double)(Z)); double X = C * (double)(Z); double m = intensity * (1 - saturation)/3; byte red = 0; byte green = 0; byte blue = 0; switch(H){ case 0: red = (byte)((int)(rescale(C,m))); green = (byte)((int)(rescale(X,m))); blue = (byte)(rescale(0,m)); break; case 1: red = (byte)((int)(rescale(X,m))); green = (byte)((int)(rescale(C,m))); blue = (byte)(rescale(0,m)); break; case 2: red = (byte)(rescale(0,m)); green = (byte)((int)(rescale(C,m))); blue = (byte)((int)(rescale(X,m))); break; case 3: red = (byte)(rescale(0,m)); green = (byte)((int)(rescale(X,m))); blue = (byte)((int)(rescale(C,m))); break; case 4: red = (byte)((int)(rescale(C,m))); green = (byte)(rescale(0,m)); blue = (byte)((int)(rescale(X,m))); break; case 5: red = (byte)((int)(rescale(X,m))); green = (byte)(rescale(0,m)); blue = (byte)((int)(rescale(C,m))); break; } return ColorBgra.FromBgr(blue,green,red); } */ double lerp(double a, double b, double t){ return a * (1 - t) + b * t ; } void PreRender(Surface dst, Surface src){ int w = src.Width; int h = src.Height; int inc_w = w + 1; int inc_h = h + 1; if (Lyapunov_Surface == null){Lyapunov_Surface = new double [w,h];} else {Array.Clear(Lyapunov_Surface, 0, w*h);} s_str_var = str_var.Length; char[] charArr=str_var.ToCharArray(); i_var = new int[s_str_var]; char temp_char; validity = true; bool a_valid = false ; bool b_valid = false ; if (s_str_var==0){ validity = false; return; } for(int pos = 0 ; pos < s_str_var ; pos++){ temp_char=Char.ToLower(charArr[pos]); i_var[pos]=(int) charArr[pos] - 97; if (i_var[pos]<0||i_var[pos]>2){ validity = false; break; } else{ switch(i_var[pos]){ case 0: a_valid = true; break; case 1: b_valid = true; break; default: break; } } } if (!a_valid||!b_valid){ validity = false; return; } float sqr_size = (float)(view_size /100); float gap = 1 - sqr_size ; float px = (float)((view_pos.First + 1) / 2); float py = (float)((view_pos.Second*-1 + 1) / 2); px*=gap; py*=gap; float lx = px * 2 + 2; float ly = py * 2 + 2; float rx = (px + sqr_size) * 2 + 2; float ry = (py + sqr_size) * 2 + 2; double md = Math.Max(w,h); double iz = lerp(2+1/(md+1),2+(md/(md+1))*2,(float)(c_pos)); int total_string_length = s_str_var * abc_repeats; int sp; double cx,cy,ix,iy,vn,limit,rn; im=0; iM=0; float f_inc_w = (float)(inc_w+1); float f_inc_h = (float)(inc_h+1); for(int x = 0 ; x < w ; x++){ for(int y = 0 ; y < h ; y++){ cx = (double)(x + 1); cy = (double)(y + 1); ix = lerp(lx,rx,cx/f_inc_w); iy = lerp(ry,ly,cy/f_inc_h); vn = .5f; limit = 0; for (int n = 0 ; n < total_string_length ; n++){ sp = n % s_str_var; sp = i_var[sp]; switch(sp){ case 0:rn=ix;break; case 1:rn=iy;break; case 2:rn=iz;break; default:rn=1;break; } vn=rn*vn*(1-vn); limit+=(float)(Math.Log(Math.Abs((double)(rn*(1-2*vn))))); } if(limit < im) {im = limit;} if(limit > iM) {iM = limit;} Lyapunov_Surface[x,y] = limit; } } } void Render(Surface dst, Surface src, Rectangle rect) { // Delete any of these lines you don't need int thick = src.Width / s_str_var; int represent; byte r; double tv,shade,t_shade; double rescale_factor = (iM-im)/255f; double d_r_a = (double)(color_a[2]); double d_g_a = (double)(color_a[1]); double d_b_a = (double)(color_a[0]); double d_r_b = (double)(color_b[2]); double d_g_b = (double)(color_b[1]); double d_b_b = (double)(color_b[0]); double nr,ng,nb; if (validity){ rescale_factor = (iM-im)/255f; } else{ rescale_factor = 1; } for (int y = rect.Top; y < rect.Bottom; y++) { if (IsCancelRequested) return; for (int x = rect.Left; x < rect.Right; x++) { switch(output_mode){ case 0: tv = (Lyapunov_Surface[x,y]-im)/(rescale_factor); if (revert_mode){ represent = 255 -(int)(tv); } else{ represent = (int)(tv); } r = (byte)(represent); dst[x,y] = ColorBgra.FromBgraClamped(r,r,r,255); break; case 1: if(Lyapunov_Surface[x,y] >= 0){ shade = Lyapunov_Surface[x,y] / iM; nr = d_r_a * shade; ng = d_g_a * shade; nb = d_b_a * shade; } else{ shade = Math.Pow(1 - Lyapunov_Surface[x,y] / im,3); nr = d_r_b * shade; ng = d_g_b * shade; nb = d_b_b * shade; } dst[x,y] = ColorBgra.FromBgraClamped((byte)((int)(nb)),(byte)((int)(ng)),(byte)((int)(nr)),255); break; } } } } Edited July 14, 2021 by Reptillian Quote G'MIC Filter Developer I am away from this forum for undetermined amount of time: If you really need anything related to my PDN plugin or my G'MIC filter within G'MIC plugin, then you can contact me via Paint.NET discord, and mention me.
Reptillian Posted July 14, 2021 Author Posted July 14, 2021 (edited) I had just updated code above. Even left some code sample to be used for HSI palette being the base for coloring the Lyapunov Fractal. Though, just from this, I find that the code is really slow. I know this is because that it is single-threaded. Doesn't look like there's much I can do about certain issues besides going into making it a gmic-pdn plugin though I prefer to avoid that route unless there's not a choice. Issues: 1. Slow speed because of it being single-threaded. 2. Lack of random HSI palette mapping. 3. The C percentage gui element cannot be grayed out if there is no 'c' in abc-string. 4. Lack of anti-aliasing. 1,2,and 4 is solved by the gmic-pdn route. 3 isn't solve-able though @midora might have an answer to that via option-based library. Edited July 14, 2021 by Reptillian Quote G'MIC Filter Developer I am away from this forum for undetermined amount of time: If you really need anything related to my PDN plugin or my G'MIC filter within G'MIC plugin, then you can contact me via Paint.NET discord, and mention me.
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.