MJW Posted May 13, 2020 Posted May 13, 2020 2 hours ago, toe_head2001 said: Obviously, writing outside of the selection is still a bad practice, and just wastes compute resources. Would you expand of this. Do you just mean the write has no effect, so the effort is wasted, or does it waste resources in some other way? If it just wastes the effort to compute the unused pixels, is that behavior that's intended to remain that way, so that it can be relied on? There are probably lots of cases where it would be convenient to clip at most to the selection's bounding rectangle, and not worry that there will be some wasted computations if the user happens to have an elliptical selection. Also, does is writing outside the ROI in Render() allowed, in the sense that it will properly write into pixels if they're selected? To paraphrase Ghostbusters, are the ROI bounds more guidelines than rules? 1 Quote
toe_head2001 Posted May 13, 2020 Posted May 13, 2020 26 minutes ago, MJW said: Do you just mean the write has no effect, so the effort is wasted Yeah, pretty much. 28 minutes ago, MJW said: is that behavior that's intended to remain that way, so that it can be relied on? I believe so. If pixels outside of the selection are modified, that would be considered a bug. 30 minutes ago, MJW said: Also, does writing outside the ROI in Render() allowed, in the sense that it will properly write into pixels if they're selected? Yes, it will work. Using the ROI is, of course, the recommended route, and probably the most efficient. 1 Quote My Gallery | My Plugin Pack Layman's Guide to CodeLab
NSD Posted July 4, 2020 Posted July 4, 2020 Swirl can be found in Effects > Distort submenu. Spoiler // Name: Swirl // Submenu: Distort // Author: NSD // Title: Swirl // Version: 1.0 // Desc: // Keywords: // URL: #region UICode DoubleSliderControl intensity = 0.0; // [-1,1] Amount / Direction DoubleSliderControl zoom = 0; // [0.0,0.999] Zoom PanSliderControl pan = Pair.Create(0.0, 0.0); // Center #endregion void Render(Surface dst, Surface src, Rectangle rect) { int x, y; double offx, offy, dx, dy, th, rd, ct, offset, xPan, yPan, zm; ColorBgra CurrentPixel; Rectangle sel = EnvironmentParameters.SelectionBounds; dst.CopySurface(src, rect.Location, rect); ct = intensity * 0.2; offset = Math.PI / 2.0; xPan = (pan.First + 1) / 2 * (sel.Right - sel.Left) + sel.Left; yPan = (pan.Second + 1) / 2 * (sel.Bottom - sel.Top) + sel.Top; zm = 1 - zoom; for (y = rect.Top; y < rect.Bottom; y++) { if (IsCancelRequested) return; for (x = rect.Left; x < rect.Right; x++) { dx = x - xPan; dy = y - yPan; rd = Math.Sqrt((dx * dx + dy * dy) * zm); th = Math.Atan2(dx, -dy) - offset; offx = rd * Math.Cos(th + ct * rd); offy = rd * Math.Sin(th + ct * rd); offx += xPan; offy += yPan; CurrentPixel = src.GetBilinearSampleWrapped((float)offx, (float)offy); dst[x,y] = CurrentPixel; } } } Swirl.zip 2 1 Quote
NSD Posted August 31, 2020 Posted August 31, 2020 (edited) This plugin can be found in the Effects Menu. You need to put OptionBasedLibrary v0.7.8 dlc and dll files in paint.net folder and WarpTextOnPath dll and dlc files in Effects folder. The UI: Spoiler // Name: WarpTextOnBezier // Submenu: // Author: NSD // Title: // Version: 1.0 // Desc: // Keywords: // URL: // Help: // Force Single Render Call #region UICode MultiLineTextboxControl text = "WARP TEXT ON A BEZIER CURVE"; // [32767] FontFamily font = new FontFamily("Georgia"); DoubleSliderControl fontSize = 120; // [5,800] Font size CheckboxControl bold = true; // Bold CheckboxControl italic = false; // Italic PanSliderControl p0 = Pair.Create(-0.500, 0.740); // PanSliderControl p1 = Pair.Create(-1.000, -1.000); // PanSliderControl p2 = Pair.Create(1.000, -1.000); // PanSliderControl p3 = Pair.Create(0.500, 0.740); // ListBoxControl<TextPathPositionEnum> textPathPosition = TextPathPositionEnum.OverPath; //|Over path|Center path|Under path ListBoxControl<RenderModeEnum> renderMode = RenderModeEnum.Normal; //|Normal|Mask|Transparent CheckboxControl viewPoints = true; // Show path #endregion Surface wrk = null; float c1, r1, c2, r2, c3, r3, c4, r4, d, r; PointF [] points; protected override void OnDispose(bool disposing) { if (disposing) { if (wrk != null) wrk.Dispose(); wrk = null; } base.OnDispose(disposing); } void PreRender(Surface dst, Surface src) { if (wrk == null) { wrk = new Surface(src.Size); } else { wrk.Clear(Color.Transparent); } Rectangle sel = EnvironmentParameters.SelectionBounds; c1 = ((float)p0.First + 1) / 2 * (sel.Right - sel.Left) + sel.Left; r1 = ((float)p0.Second + 1) / 2 * (sel.Bottom - sel.Top)+ sel.Top; c2 = ((float)p1.First + 1) / 2 * (sel.Right - sel.Left) + sel.Left;; r2 = ((float)p1.Second + 1) / 2 * (sel.Bottom - sel.Top)+ sel.Top;; c3 = ((float)p2.First + 1) / 2 * (sel.Right - sel.Left) + sel.Left;; r3 = ((float)p2.Second + 1) / 2 * (sel.Bottom - sel.Top)+ sel.Top;; c4 = ((float)p3.First + 1) / 2 * (sel.Right - sel.Left) + sel.Left;; r4 = ((float)p3.Second + 1) / 2 * (sel.Bottom - sel.Top)+ sel.Top;; Size selSize = EnvironmentParameters.SelectionBounds.Size; d = Math.Min(selSize.Width, selSize.Height) / 20; if (d <= 1) return; r = d / 2; points = new PointF[4]; points[0] = new PointF(c1, r1); points[1] = new PointF(c2, r2); points[2] = new PointF(c3, r3); points[3] = new PointF(c4, r4); } void Render(Surface dst, Surface src, Rectangle rect) { dst.CopySurface(src, rect.Location, rect); using (RenderArgs ra = renderMode == 0 ? new RenderArgs(dst) : new RenderArgs(wrk)) using (GraphicsPath textPath = new GraphicsPath()) using (SolidBrush sBrush = new SolidBrush(Color.Blue)) using (Pen pen = new Pen(Color.FromArgb(255, Color.Red), 3)) using (SolidBrush pointBr = new SolidBrush(Color.YellowGreen)) { pen.LineJoin = LineJoin.Round; pen.DashStyle = DashStyle.Solid; Graphics g = ra.Graphics; g.Clip = new Region(rect); g.SmoothingMode = SmoothingMode.AntiAlias; g.TextRenderingHint = TextRenderingHint.AntiAlias; FontStyle myStyle = FontStyle.Regular; if (bold) myStyle |= FontStyle.Bold; if (italic) myStyle |= FontStyle.Italic; Font fnt = new Font(font.Name, (float)fontSize, myStyle); FontFamily ff = new FontFamily(font.Name); StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Near; format.LineAlignment = StringAlignment.Near; switch (textPathPosition) { case TextPathPositionEnum.CenterPath: format.Alignment = StringAlignment.Near; format.LineAlignment = StringAlignment.Center; break; case TextPathPositionEnum.OverPath: format.Alignment = StringAlignment.Near; format.LineAlignment = StringAlignment.Far; break; case TextPathPositionEnum.UnderPath: format.Alignment = StringAlignment.Near; format.LineAlignment = StringAlignment.Near; break; } if (viewPoints) { g.DrawBeziers(pen, points); pen.DashStyle = DashStyle.Dash; g.DrawLine(pen, c1, r1, c2, r2); g.DrawLine(pen, c3, r3, c4, r4); pen.DashStyle = DashStyle.Solid; g.FillEllipse(pointBr, new RectangleF(c1 - r, r1 - r, d, d)); g.DrawEllipse(Pens.Black, new RectangleF(c1 - r, r1 - r, d, d)); g.DrawString("1", new Font("Tahoma", r), Brushes.Black, new RectangleF(c1 - 0.7f * r, r1 - r, d, d)); g.FillEllipse(pointBr, new RectangleF(c2 - r, r2 - r, d, d)); g.DrawEllipse(Pens.Black, new RectangleF(c2 - r, r2 - r, d, d)); g.DrawString("2", new Font("Tahoma", r), Brushes.Black, new RectangleF(c2 - 0.7f * r, r2 - r, d, d)); g.FillEllipse(pointBr, new RectangleF(c3 - r, r3 - r, d, d)); g.DrawEllipse(Pens.Black, new RectangleF(c3 - r, r3 - r, d, d)); g.DrawString("3", new Font("Tahoma", r), Brushes.Black, new RectangleF(c3 - 0.7f * r, r3 - r, d, d)); g.FillEllipse(pointBr, new RectangleF(c4 - r, r4 - r, d, d)); g.DrawEllipse(Pens.Black, new RectangleF(c4 - r, r4 - r, d, d)); g.DrawString("4", new Font("Tahoma", r), Brushes.Black, new RectangleF(c4 - 0.7f * r, r4 - r, d, d)); } textPath.AddString(text, ff, (int)myStyle, (float)fontSize, new PointF(0, 0), format); if(text.Length > 0) { g.DrawPath(pen, BezierWarp(textPath, g)); g.FillPath(sBrush, BezierWarp(textPath, g)); } if (renderMode == RenderModeEnum.Mask)//creates mask { for (int y = rect.Top; y < rect.Bottom; y++) { if (IsCancelRequested) return; for (int x = rect.Left; x < rect.Right; x++) { ColorBgra CurrentPixel = src[x, y]; CurrentPixel.A = Int32Util.ClampToByte(wrk[x, y].A); dst[x, y] = CurrentPixel; } } } if (renderMode == RenderModeEnum.Transparent)//Transparent checked { for (int y = rect.Top; y < rect.Bottom; y++) { if (IsCancelRequested) return; for (int x = rect.Left; x < rect.Right; x++) { ColorBgra CurrentPixel = src[x, y]; CurrentPixel.A = Int32Util.ClampToByte(255 - wrk[x, y].A); dst[x, y] = CurrentPixel; } } } } } GraphicsPath BezierWarp(GraphicsPath textPath, Graphics g) { // Calculate coefficients A thru H from the control points float A = c4 - 3 * c3 + 3 * c2 - c1; float B = 3 * c3 - 6 * c2 + 3 * c1; float C = 3 * c2 - 3 * c1; float D = c1; float E = r4 - 3 * r3 + 3 * r2 - r1; float F = 3 * r3 - 6 * r2 + 3 * r1; float G = 3 * r2 - 3 * r1; float H = r1; PointF[] pathPoints = textPath.PathPoints; RectangleF textBounds = textPath.GetBounds(); for (int i = 0; i < pathPoints.Length; i++) { PointF pt = pathPoints[i]; float textX = pt.X; float textY = pt.Y; // Normalize the x coordinate into the parameterized // value with a domain between 0 and 1. float t = textX / textBounds.Width; float t2 = (t * t); float t3 = (t * t * t); // Calculate spline point for parameter t float Sx = A * t3 + B * t2 + C * t + D; float Sy = E * t3 + F * t2 + G * t + H; // Calculate the tangent vector for the point float Tx = 3 * A * t2 + 2 * B * t + C; float Ty = 3 * E * t2 + 2 * F * t + G; // Rotate 90 or 270 degrees to make it a perpendicular float Px = - Ty; float Py = Tx; // Normalize the perpendicular into a unit vector float magnitude = (float)Math.Sqrt((Px * Px) + (Py * Py)); Px /= magnitude; Py /= magnitude; // Assume that input text point y coord is the "height" or // distance from the spline. Multiply the perpendicular // vector with y. it becomes the new magnitude of the vector Px *= textY; Py *= textY; // Translate the spline point using the resultant vector float finalX = Px + Sx; float finalY = Py + Sy; pathPoints[i] = new PointF(finalX, finalY); } return new GraphicsPath(pathPoints, textPath.PathTypes); } enum TextPathPositionEnum { OverPath, CenterPath, UnderPath } enum RenderModeEnum { Normal, Mask, Transparent } WarpTextOnPath.zip http://www.mediafire.com/file/ignc6de43v3m90e/WarpTextOnPathOB.zip/file Edited October 30, 2020 by NSD Added the code. 2 3 Quote
Seerose Posted September 1, 2020 Posted September 1, 2020 ❤️ @NSD! Welcome to our family. Thank you so much for your effort. 🧁 ☕ 1 Quote Live as if you were to die tomorrow. Learn as if you were to live forever. Gandhi
sh0sh1n Posted October 29, 2020 Posted October 29, 2020 On 8/31/2020 at 11:42 AM, NSD said: This plugin can be found in the Effects Menu. You need to put OptionBasedLibrary v0.7.8 dlc and dll files in paint.net folder and WarpTextOnPath dll and dlc files in Effects folder. The UI: WarpTextOnPath.zip 174.27 kB · 10 downloads Is there a way to install this on the Windows Store version of Paint? I feel kind of gypped that I purchased the app to support the developer after a good decade of free use, and it seems super difficultr to install plugins now Quote
Ego Eram Reputo Posted October 29, 2020 Posted October 29, 2020 It is not difficult. It requires a once-only setup of the correct folder structure. See the instructions in the yellow panel on this page: https://www.getpaint.net/doc/latest/InstallPlugins.html#4 Quote ebook: Mastering Paint.NET | resources: Plugin Index | Stereogram Tut | proud supporter of Codelab plugins: EER's Plugin Pack | Planetoid | StickMan | WhichSymbol+ | Dr Scott's Markup Renderer | CSV Filetype | dwarf horde plugins: Plugin Browser | ShapeMaker
Reptillian Posted November 2, 2020 Posted November 2, 2020 (edited) EDIT : Never mind, solved the speed issue. Edited November 3, 2020 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.
NSD Posted November 5, 2020 Posted November 5, 2020 Is there a way to find out in plugins if a selection is tilted at a certain angle? These angles are displayed in the status bar in the pdn app. Quote
Reptillian Posted November 7, 2020 Posted November 7, 2020 Now, made something else. I think this is likely my final plugin for PDN as I don't think it makes sense to convert some of my other gmic work given either they're too long, or has features that are way too difficult to implement. Plugin to download below. I hope it's good enough since there are slowdown issues. Rotate by Torus Map.zip 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.
Djisves Posted November 7, 2020 Posted November 7, 2020 On 8/31/2020 at 6:42 PM, NSD said: This plugin can be found in the Effects Menu. @NSD, wouldn't it make sense if Wrap Text on Path was placed in the "Text Formations" sub-menu? Quote
NSD Posted November 7, 2020 Posted November 7, 2020 (edited) You're right, but the advantage of using OptionBased is that the users can place the plugin where they want. To do this edit the .dlc file of plugin as follows: 1. change the extension from .dlc to .txt 2. open it with Notepad 3. the following line needs to be changed:WarpTextOnPathEffectPlugin.SubmenuName=Text Formations 3. save the changes, close Notepad and then change the extension back to .dlc That's all. Now start PDN. Edited November 8, 2020 by NSD typo 1 Quote
ReMake Posted November 7, 2020 Posted November 7, 2020 1 hour ago, NSD said: 1. change the extension from .dlc to .txt File .dlc in any text editor can be opened and saved without changing the extension. 1 Quote
Djisves Posted November 8, 2020 Posted November 8, 2020 Thank you @NSD and @ReMake. I copied and pasted the text above only for the plugin to disappear altogether. It was not in Effects, neither in Effects > Text Formations. I tried again without the spaces either side of "=" and it worked. It may have been a fluke, bit I thought I'd mention it anyway. When (if?) the plugin is released in the main plugin forum, I think it would perhaps be easier for everyone if it was placed in the text sub-menu outright. 1 Quote
NSD Posted December 15, 2020 Posted December 15, 2020 I created this plugin for personal purposes. Because there are already several such plugins I will not post it in the dedicated tread. If you like it use it. If you don't like it, I'm sorry. AlignNSD.zip 1 2 Quote
Reptillian Posted December 15, 2020 Posted December 15, 2020 I don't plan to download and use that, but going to compliment you on the GUI design. I like the design of it and the features there. 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.
NSD Posted December 19, 2020 Posted December 19, 2020 (edited) Diffusion plugin The plugin is in Effects > Stylize submenu. The UI: Diffusion.zip Edited December 19, 2020 by NSD 1 1 Quote
NSD Posted March 5, 2021 Posted March 5, 2021 (edited) The effect of this plugin is similar to that obtained by Rotate / Zoom except that the zoom is centered on the created selection. To see the center of the selection click on the Move Selection tool and notice where the small circle marked with + is. If there is no selection it zooms the entire canvas. The plugin is inspired by the discussion on this thread: https://forums.getpaint.net/topic/117885-zoomin-plugin/ It is located in Effects -> Selection submenu. Zoom Selection.zip LE: @Djisves pointed out to me that there is already another plugin that I missed and that does the same thing much better and has more options: Edited March 7, 2021 by NSD Added more information. 1 2 Quote
Reptillian Posted June 14, 2021 Posted June 14, 2021 (edited) As soon as I have figured out how to work with HSV in content of PDN C# development, I was able to almost complete the plugin. For now, I am releasing as a test plugin, and there is only one more thing to complete functionality-wise (No, I won't bother getting the plugin to automatically disable colors on circumstances), and that is getting the seed to work. I don't know how to fix that. Here's the current build of the Random Gradient Bars plugin. Let me know if there is any bugs outside of those two I mentioned. Random Gradient Bars.zip Source Code: Spoiler // Name: Random Gradient Bars // Submenu: Render // Author: Reptillian // Title: Random Gradient Bars // Version: .75 // Desc: Generates Random Gradient Bars onto the canvas // Keywords: Render, Bars // URL: https://forums.getpaint.net/profile/85868-reptillian/ // Help: #region UICode ReseedButtonControl seed = 0; // Reseed IntSliderControl bar_size = 50; // [1,256] Bar Size IntSliderControl space_size = 0; // [0,256] Space Size AngleControl degree = 45; // [-180,180] Angle DoubleSliderControl skew_degree = 0; // [-89,89] Skew Angle PanSliderControl origin = Pair.Create(0.000, 0.000); // Origin IntSliderControl sublevel = 0; // [0,3] Subsampling DoubleSliderControl shift = 0; // [0,100] Shift DoubleSliderControl mult_1 = 0.1; // [0.1,256] Multiplier A DoubleSliderControl mult_2 = 100; // [0.1,256] Multiplier B ListBoxControl repetition_mode = 0; // Repetition|Random|Cut|Periodic|Continuous ListBoxControl<Random_Repetition_Mode> repetition_random_repetition_modes = 0; // {repetition_mode} Random Bar Repetition|All|Cut and Periodic|Cut and Continuous|Periodic and Continuous ListBoxControl<CS_Mode> color_space = 0; // Color|Gray|Duotone|Random-RGB|Random-HSV ListBoxControl<Space_Mode> space_mode = 0; // Space Mode|Alpha|Cut|Gradient ListBoxControl<Sym_Mode> symmetry = 0; // Symmetry Mode|N/A|A|B CheckboxControl inversion_mode = false; // Use Inversion ColorWheelControl space_color_a = ColorBgra.FromBgr(0, 140, 255); // [DarkOrange] Space Color A ColorWheelControl space_color_b = ColorBgra.FromBgr(0, 215, 255); // [Gold] Space Color B #endregion double[] v_base = null; double[] v_shift = null; double[] v_mult = null; int[] v_modulo_out = null; bool[] v_invert = null; int[] v_hue = null; int[] v_rgb_r = null; int[] v_rgb_g = null; int[] v_rgb_b = null; double ang; int number_of_bars; int shift_bars; double cut(double a,double b,double c){ double min_val = Math.Min(b,c); double max_val = Math.Max(b,c); return (a < min_val) ? min_val : (a > max_val) ? max_val : a; } double fmod(double a, double b){ return a - Math.Floor(a / b) ; } int imod(int a, int b){ int r = a % b; return r < 0 ? r + b : r; } double fmod_cont(double a, double b){ double ind = imod((int)(Math.Floor(a/b)),2) ; return ind == 1 ? b - fmod(a,b) : fmod(a,b) ; } double fcut(double a, double b){ return (cut(a,-b,b)+b)/2 ; } double rot_x(double a, double b, double sin_ang, double cos_ang){ return a * cos_ang - b * sin_ang ; } double rot_y(double a, double b, double sin_ang, double cos_ang){ return a * sin_ang + b * cos_ang ; } double lerp(double a, double b, double t){ return a * (1 - t) + b * t ; } ColorBgra lerp_HSV(HsvColor B,HsvColor A,double t){ double A_H = (double)(A.Hue); double A_S = (double)(A.Saturation); double A_V = (double)(A.Value); double B_H = (double)(B.Hue); double B_S = (double)(B.Saturation); double B_V = (double)(B.Value); double d_NH = lerp(A_H,B_H,t); double d_NS = lerp(A_S,B_S,t); double d_NV = lerp(A_V,B_V,t); int NH = (int)(Math.Round(d_NH)); int NS = (int)(Math.Round(d_NS)); int NV = (int)(Math.Round(d_NV)); HsvColor new_hsv = new HsvColor(NH,NS,NV); return ColorBgra.FromColor(new_hsv.ToColor()); } ColorBgra fromHueandValue(int Hue,double t){ HsvColor new_hsv = new HsvColor(Hue,100,(int)(Math.Round(t*100))); return ColorBgra.FromColor(new_hsv.ToColor()); } void PreRender(Surface dst, Surface src) { Random myRandom = new Random(int.MaxValue); Random myRandom_2 = new Random(int.MaxValue); Random myRandom_3 = new Random(int.MaxValue); int ww = src.Width - 1 ; int hh = src.Height - 1 ; double cx = (double)(ww) / 2 ; double cy = (double)(hh) / 2 ; double cut_ang = Math.Atan2(cy,cx) ; double cut_ang_2 = Math.PI - cut_ang ; ang = ( degree / 180 ) / Math.PI ; double trimmed_ang = ang % Math.PI ; bool use_shift = shift > 0 ; int total_width = bar_size + space_size; double d_total_width = (double)(total_width); double d_ww = (double)(ww); double d_hh = (double)(hh); if ((trimmed_ang>=cut_ang)&&(trimmed_ang<cut_ang)){ number_of_bars =(int)(Math.Ceiling((Math.Abs(1/Math.Sin(ang))*d_ww)/d_total_width)); } else { number_of_bars =(int)(Math.Ceiling((Math.Abs(1/Math.Cos(ang))*d_hh)/d_total_width)); } shift_bars = number_of_bars / 2; v_base = new double[number_of_bars]; v_modulo_out = new int[number_of_bars]; v_invert = new bool[number_of_bars]; v_shift = new double[number_of_bars]; for(int n = 0 ; n < number_of_bars ; n++){ v_base[n] = 0; v_invert[n] = false ; } Array.Copy(v_base, v_shift, v_base.Length); double shift_dist; int precision = 100000; if (use_shift){ for(int n = 0 ; n < number_of_bars ; n++){ shift_dist = (double)(myRandom_3.Next(precision)) / (double)(precision) ; shift_dist*=shift; if (myRandom_3.Next(255) > 128){ v_shift[n] = shift_dist; } else{ v_shift[n] = -shift_dist; } } } if (repetition_mode > 0) { int rep_pos=repetition_mode - 1 ; for(int n = 0 ; n < number_of_bars ; n++){ v_modulo_out[n]=rep_pos; } } else{ switch(repetition_random_repetition_modes){ case Random_Repetition_Mode.Cut_Periodic: for(int n = 0 ; n < number_of_bars ; n++){ v_modulo_out[n] = myRandom.Next(2); } break; case Random_Repetition_Mode.Cut_Continuous: for(int n = 0 ; n < number_of_bars ; n++){ v_modulo_out[n] = myRandom.Next(2)*2; } break; case Random_Repetition_Mode.Periodic_Continuous: for(int n = 0 ; n < number_of_bars ; n++){ v_modulo_out[n] = myRandom.Next(2)+1; } break; default: for(int n = 0 ; n < number_of_bars ; n++){ v_modulo_out[n] = myRandom.Next(3); } break; } } if (inversion_mode){ for(int n = 0 ; n < number_of_bars ; n++){ if (myRandom_2.Next(255) > 128){ v_invert[n] = true; } } } v_hue = new int[number_of_bars]; v_rgb_r = new int[number_of_bars]; v_rgb_g = new int[number_of_bars]; v_rgb_b = new int[number_of_bars]; v_mult = new double[number_of_bars]; for(int n = 0 ; n < number_of_bars ; n++){ v_hue[n] = myRandom.Next(359); v_rgb_r[n] = myRandom.Next(255); v_rgb_g[n] = myRandom.Next(255); v_rgb_b[n] = myRandom.Next(255); v_mult[n] = lerp(mult_1,mult_2,(double)(myRandom.Next(precision))/(double)(precision)); } } void Render(Surface dst, Surface src, Rectangle rect) { // Delete any of these lines you don't need int ww = src.Width - 1 ; int hh = src.Height - 1 ; double d_ww = (double)(ww); double d_hh = (double)(hh); double sd = Math.Max(d_ww,d_hh)/Math.Min(d_ww,d_hh); double sx = d_ww>d_hh?sd:1; double sy = d_ww>d_hh?1:sd; double cx = (double)(ww) / 2 ; double cy = (double)(hh) / 2 ; double ox = cx - ((double)(cx)*-origin.First); double oy = cy - ((double)(cy)*-origin.Second); double ww_div_sx = (double)(ww)/sx; double hh_div_sy = (double)(hh)/sy; double pyth_img = Math.Sqrt(d_ww*d_ww+d_hh*d_hh); double ren_ang = ( degree / 180 ) * Math.PI ; double skew_ang = ( skew_degree / 180)*Math.PI; double cos_ang = Math.Cos(ren_ang); double sin_ang = Math.Sin(ren_ang); double mdist = Math.Tan(skew_ang)*pyth_img; int total_width = bar_size + space_size; bool width_test = total_width>1; bool bar_and_space_test = (bar_size==1)&&(space_size<2); bool space_test = space_size > 0; int half_total_width = width_test ? total_width / 2 : 0 ; double initial_x,initial_y,spacing,gradient,point_x,new_gradient,final_gradient; int bar,bar_id,use_modulo_out; bool spaces; double temp_result; double temp_result_2; bool gradient_test; int sc_a_B = Convert.ToInt32(space_color_a.B); int sc_a_G = Convert.ToInt32(space_color_a.G); int sc_a_R = Convert.ToInt32(space_color_a.R); int sc_b_B = Convert.ToInt32(space_color_b.B); int sc_b_G = Convert.ToInt32(space_color_b.G); int sc_b_R = Convert.ToInt32(space_color_b.R); Color rgb_1 = space_color_a.ToColor(); Color rgb_2 = space_color_b.ToColor(); HsvColor hsv_color_a = HsvColor.FromColor(rgb_1); HsvColor hsv_color_b = HsvColor.FromColor(rgb_2); if (bar_and_space_test){ spacing = (space_size>0)?.5:0; } else{ spacing = 1 - ((double)(space_size)/((double)(total_width) - 1)); } for (int y = rect.Top; y < rect.Bottom; y++) { if (IsCancelRequested) return; for (int x = rect.Left; x < rect.Right; x++) { initial_x = ((double)(x) - ox) / d_ww * sx; initial_y = ((double)(y) - oy ) / d_hh * sy; gradient = -rot_y(initial_x,initial_y,sin_ang,cos_ang)*hh_div_sy/pyth_img; point_x = rot_x(initial_x,initial_y,sin_ang,cos_ang)*ww_div_sx+gradient*mdist+half_total_width; bar_id = (int)(Math.Floor(point_x/total_width)); switch(symmetry){ case Sym_Mode.B: bar = imod(-Math.Abs(bar_id)+shift_bars,number_of_bars);break; case Sym_Mode.A: bar = imod(Math.Abs(bar_id)+shift_bars,number_of_bars);break; default: bar = imod(bar_id+shift_bars,number_of_bars);break; } if(bar_and_space_test) { if (space_test){ spaces = imod((int)(point_x),2) == 1 ; } else{ spaces = true; } } else { spaces = 2*Math.Abs(fmod(point_x/total_width,1)-.5)<=spacing; } new_gradient = gradient * v_mult[bar] + v_shift[bar]; use_modulo_out = v_modulo_out[bar]; switch(use_modulo_out){ case 2: final_gradient = v_invert[bar] ? 1 - fmod_cont(new_gradient,1) : fmod_cont(new_gradient,1); break; case 1: final_gradient = v_invert[bar] ? 1 - fmod(new_gradient,1) : fmod(new_gradient,1); break; default: final_gradient= v_invert[bar] ? 1 - fcut(new_gradient,1) : fcut(new_gradient,1); break; } switch(color_space){ case CS_Mode.HSV_Random: switch(space_mode){ case Space_Mode.Gradient: temp_result = cut(gradient*2+.5,0,1); if (spaces){ dst[x,y]=fromHueandValue(v_hue[bar],final_gradient); } else{ dst[x,y]=lerp_HSV(hsv_color_a,hsv_color_b,temp_result); } break; case Space_Mode.Cut: gradient_test = gradient >= 0; if (spaces){ dst[x,y]=fromHueandValue(v_hue[bar],final_gradient); } else{ dst[x,y]=ColorBgra.FromBgr( (byte)((int)(gradient_test?sc_a_B:sc_b_B)), (byte)((int)(gradient_test?sc_a_G:sc_b_G)), (byte)((int)(gradient_test?sc_a_R:sc_b_R)) ); } break; default: if (spaces){ dst[x,y]=fromHueandValue(v_hue[bar],final_gradient); } else{ dst[x,y]=ColorBgra.FromBgra(0,0,0,0); } break; } break; case CS_Mode.RGB_Random: switch(space_mode){ case Space_Mode.Gradient: temp_result = cut(gradient*2+.5,0,1); dst[x,y]=ColorBgra.FromBgr( (byte)(spaces ? (int)(v_rgb_b[bar] * final_gradient) : (int)(lerp((double)(sc_b_B),(double)(sc_a_B),temp_result))), (byte)(spaces ? (int)(v_rgb_g[bar] * final_gradient) : (int)(lerp((double)(sc_b_G),(double)(sc_a_G),temp_result))), (byte)(spaces ? (int)(v_rgb_r[bar] * final_gradient) : (int)(lerp((double)(sc_b_R),(double)(sc_a_R),temp_result))) ); break; case Space_Mode.Cut: gradient_test = gradient >= 0; dst[x,y]=ColorBgra.FromBgr( (byte)(spaces ? (int)(v_rgb_b[bar] * final_gradient) : (int)(gradient_test ? sc_a_B : sc_b_B)), (byte)(spaces ? (int)(v_rgb_g[bar] * final_gradient) : (int)(gradient_test ? sc_a_G : sc_b_G)), (byte)(spaces ? (int)(v_rgb_r[bar] * final_gradient) : (int)(gradient_test ? sc_a_R : sc_b_R)) ); break; default: dst[x,y]=ColorBgra.FromBgra( (byte)((int)(v_rgb_b[bar] * final_gradient)), (byte)((int)(v_rgb_g[bar] * final_gradient)), (byte)((int)(v_rgb_r[bar] * final_gradient)), (byte)(spaces ? 255 : 0) ); break; } break; case CS_Mode.Duotone: switch(space_mode){ case Space_Mode.Gradient: temp_result = cut(gradient*2+.5,0,1); dst[x,y]=ColorBgra.FromBgr( (byte)(spaces ? (int)(lerp((double)(sc_a_B),(double)(sc_b_B),final_gradient)) : (int)(lerp((double)(sc_b_B),(double)(sc_a_B),temp_result))), (byte)(spaces ? (int)(lerp((double)(sc_a_G),(double)(sc_b_G),final_gradient)) : (int)(lerp((double)(sc_b_G),(double)(sc_a_G),temp_result))), (byte)(spaces ? (int)(lerp((double)(sc_a_R),(double)(sc_b_R),final_gradient)) : (int)(lerp((double)(sc_b_R),(double)(sc_a_R),temp_result))) ); break; case Space_Mode.Cut: gradient_test = gradient >= 0; dst[x,y]=ColorBgra.FromBgr( (byte)(spaces ? (int)(lerp((double)(sc_a_B),(double)(sc_b_B),final_gradient)) : (int)(gradient_test ? sc_a_B : sc_b_B)), (byte)(spaces ? (int)(lerp((double)(sc_a_G),(double)(sc_b_G),final_gradient)) : (int)(gradient_test ? sc_a_G : sc_b_G)), (byte)(spaces ? (int)(lerp((double)(sc_a_R),(double)(sc_b_R),final_gradient)) : (int)(gradient_test ? sc_a_R : sc_b_R)) ); break; default: dst[x,y]=ColorBgra.FromBgra( (byte)((int)(lerp((double)(sc_a_B),(double)(sc_b_B),final_gradient))), (byte)((int)(lerp((double)(sc_a_G),(double)(sc_b_G),final_gradient))), (byte)((int)(lerp((double)(sc_a_R),(double)(sc_b_R),final_gradient))), (byte)(spaces ? 255 : 0) ); break; } break; default: switch(space_mode){ case Space_Mode.Gradient: temp_result = Math.Round(255 * final_gradient); temp_result_2 = cut(gradient*2+.5,0,1) * 255; temp_result = spaces ? temp_result : temp_result_2; dst[x,y]=ColorBgra.FromBgr((byte)(temp_result),(byte)(temp_result),(byte)(temp_result)); break; case Space_Mode.Cut: temp_result = spaces ? Math.Round(255 * final_gradient) : (gradient >= 0 ? 255 : 0); dst[x,y]=ColorBgra.FromBgr((byte)(temp_result),(byte)(temp_result),(byte)(temp_result)); break; default: temp_result = Math.Round(255 * final_gradient); dst[x,y]=ColorBgra.FromBgra((byte)(temp_result),(byte)(temp_result),(byte)(temp_result),(byte)(spaces ? 255 : 0)); break; } break; } } } } enum Random_Repetition_Mode{ All, Cut_Periodic, Cut_Continuous, Periodic_Continuous } enum CS_Mode{ Grayscale, Duotone, RGB_Random, HSV_Random } enum Space_Mode{ Alpha, Cut, Gradient } enum Sym_Mode{ None, A, B, } Edited June 14, 2021 by Reptillian Added enum into C# Source Code. 1 1 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.
lynxster4 Posted June 15, 2021 Posted June 15, 2021 That's pretty cool @Reptillian! I could see me using this. You're getting good at C# code. Keep up the good work. 😊 Quote My Art Gallery | My Shape Packs | ShapeMaker Mini Tut | Air Bubble Stained Glass Chrome Text with Reflections | Porcelain Text w/ Variegated Coloring | Realistic Knit PatternOpalescent Stained Glass | Frosted Snowman Cookie | Leather Texture | Plastic Text | Silk Embroidery Visit my Personal Website "Never, ever lose your sense of humor - you'll live longer"
NSD Posted July 24, 2021 Posted July 24, 2021 (edited) This plugin is located in Effects > Tools. DrawingTool.zip Edited November 18, 2021 by NSD Replace with new version. 3 Quote
lynxster4 Posted July 24, 2021 Posted July 24, 2021 This is pretty neat @NSD! Selecting the Polygon and playing with the 'Tens and 'Arc' gives you limitless shapes. Maybe a little more information about these two selections would be beneficial for everyone. I simply played with them to see what they do. Thank you for coding this. ☺️ 2 1 Quote My Art Gallery | My Shape Packs | ShapeMaker Mini Tut | Air Bubble Stained Glass Chrome Text with Reflections | Porcelain Text w/ Variegated Coloring | Realistic Knit PatternOpalescent Stained Glass | Frosted Snowman Cookie | Leather Texture | Plastic Text | Silk Embroidery Visit my Personal Website "Never, ever lose your sense of humor - you'll live longer"
Red ochre Posted July 24, 2021 Posted July 24, 2021 Well done @NSD very impressive! ⭐ Quote Red ochre Plugin pack.............. Diabolical Drawings ................Real Paintings
NSD Posted July 24, 2021 Posted July 24, 2021 Thanks, but I need to clarify the limitations of this plugin. The implemented Undo function is extremely simple, so that each time the left mouse button is lifted, the entire canvas is saved in memory. This means extremely high memory consumption depending on the complexity of the drawing and the size of the canvas. It is advisable to save the drawing on the canvas from time to time with the OK button. At this point the memory is freed. If you do not move the drawing on the canvas you will be able to continue it when the plugin is run again. The grid will fit perfectly. Quote
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.