xod Posted February 9, 2020 Author Share Posted February 9, 2020 (edited) Custom Corner Frame plugin is located in Effects>>Render submenu Download Edited February 13, 2020 by xod Replaced with a new version. 5 1 Quote Link to comment Share on other sites More sharing options...
Eli Posted February 9, 2020 Share Posted February 9, 2020 Thanks @xod for coming to the rescue. Quote Link to comment Share on other sites More sharing options...
HyReZ Posted February 9, 2020 Share Posted February 9, 2020 @xod Thanks for the timely update. I had thought that your original plugin had the features that Eli requested when I check yesterday and today it does. Quick work indeed! Quote Link to comment Share on other sites More sharing options...
lynxster4 Posted February 9, 2020 Share Posted February 9, 2020 Perfect @xod! 2 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" Link to comment Share on other sites More sharing options...
HyReZ Posted February 9, 2020 Share Posted February 9, 2020 2 Quote Link to comment Share on other sites More sharing options...
Eli Posted February 11, 2020 Share Posted February 11, 2020 (edited) Hello @xod , I have updated to the new version of Custom Corner Frame and I get an error when I try to use it. I did not get this error with the previous version. Spoiler File: C:\Program Files\Paint.NET\Effects\CustomCornerFrame.dll Name: CustomCornerFrameEffect.CustomCornerFrameEffectPlugin Version: 1.0.1.0 Author: Copyright ©2020 by xod Copyright: Custom Corner Frame Website: https://forums.getpaint.net/ Full error message: System.MissingMethodException: Method not found: 'System.Drawing.Rectangle PaintDotNet.Effects.EffectEnvironmentParameters.get_SelectionBounds()'. at CustomCornerFrameEffect.CustomCornerFrameEffectPlugin.OnSetupOptions(OptionContext optContext) at OptionBased.Effects.OptionBasedEffect.CreateConfigDialog() at PaintDotNet.Menus.EffectMenuBase.RunEffectImpl(Type effectType) in D:\src\pdn\src\PaintDotNet\Menus\EffectMenuBase.cs:line 873 Edited February 11, 2020 by Eli Problem solved when I updated to latest version of Paint.Net :) Quote Link to comment Share on other sites More sharing options...
xod Posted February 11, 2020 Author Share Posted February 11, 2020 BoltBait explains in the Creative Text Pro v1.0 plugin code: // For older Paint.NET use this line instead of the next: // Rectangle selection = EnvironmentParameters.GetSelection(srcBounds).GetBoundsInt(); Rectangle selection = EnvironmentParameters.SelectionBounds; So, you did the right thing: Paint.net update. Quote Link to comment Share on other sites More sharing options...
xod Posted February 29, 2020 Author Share Posted February 29, 2020 This plugin is based on Alexander Seel's code -> Text on Path with VB.NET and TechnoRobbo's code -> SplineMaster. The plugin is located in Effects ► Text Formations. It is slow on large canvas. Text_on_Path.zip 1 2 Quote Link to comment Share on other sites More sharing options...
lynxster4 Posted February 29, 2020 Share Posted February 29, 2020 Rep you tomorrow @xod. Thanks so much! 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" Link to comment Share on other sites More sharing options...
Eli Posted March 24, 2020 Share Posted March 24, 2020 Hi @xod I have been enjoying the Custom Corner Frame plugin so much that I want it double if possible . It must be because I have been locked at home for 10 days already. Spoiler 😄 2 Quote Link to comment Share on other sites More sharing options...
xod Posted March 24, 2020 Author Share Posted March 24, 2020 This plugin together with 'Trail' from pyrochild allows you to get a 3D text. It is located in Effects ► Text Formations. The UI SkewedRotatedText.zip 1 5 Quote Link to comment Share on other sites More sharing options...
lynxster4 Posted March 24, 2020 Share Posted March 24, 2020 @xod .... you are the 'TEXT' man! Keep it up. 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" Link to comment Share on other sites More sharing options...
Reptillian Posted May 12, 2020 Share Posted May 12, 2020 (edited) I could not get this filter to work, so I decided to dump this in this thread in case anyone wants to finish and is searching for unfinished plugin // Name: Axis-Based Shift Grouped Pixel to Boundary // Submenu: Effects / Distortion // Author: Reptorian // Title: Axis-Based Shift Grouped Pixel to Boundary // Version: .5 // Desc: Incomplete filter. // Keywords: // URL: // Help: #region UICode DoubleSliderControl positionperc = 0; // [-100,100] Position of Pixels (%) DoubleSliderControl influenceperc = 100; // [0,100] Influence Factor (%) IntSliderControl alpha_threshold = 255; // [1,255] Alpha Threshold ListBoxControl axis = 1; // Axis|Horizontal|Vertical #endregion int[] rowNonZeroAlphas = null; int[] columnNonZeroAlphas = null; void PreRender(Surface dst, Surface src) { int w = src.Width, h = src.Height; if (rowNonZeroAlphas == null) { columnNonZeroAlphas = new int[w]; rowNonZeroAlphas = new int[h]; for (int x = 0; x < w; x++) { int nonZeroAlphaCount = 0; for (int y = 0; y < h; y++) { if (src[x,y].A >= alpha_threshold) {nonZeroAlphaCount++;} columnNonZeroAlphas[x] = nonZeroAlphaCount; dst[x,y]=ColorBgra.FromBgra(0,0,0,0); } } for (int y = 0; y < h; y++) { int nonZeroAlphaCount = 0; for (int x = 0; x < w; x++) { if (src[x,y].A >= alpha_threshold) {nonZeroAlphaCount++;} rowNonZeroAlphas[y] = nonZeroAlphaCount; } } } else { for (int x = 0; x < w; x++) { for (int y = 0; y < h; y++) { dst[x,y]=ColorBgra.FromBgra(0,0,0,0); } } } } void Render(Surface dst, Surface src, Rectangle rect) { double position = (positionperc / 100 + 1) / 2; double influence_factor = influenceperc / 100; double invert_factor = 1 - influence_factor; int w = rect.Right; int h = rect.Bottom; int tx,ty,nx,ny,fx,fy,N; double tny,tnx; if (axis==1) { for (int x = 0; x < w; x++) { if (IsCancelRequested) return; ny = h - 1; if (columnNonZeroAlphas[x] != 0) { N=columnNonZeroAlphas[x]; ty = h - N ; ny-=(int)(ty*position); for (int y = h - 1; y >= 0; y--) { if (N != 0) { if (src[x,y].A >= alpha_threshold) { tny = influence_factor * (double)(ny) + invert_factor*(double)(y); if (position == 1) { fy=(int)(Math.Ceiling(tny)); } else { fy=(int)(Math.Floor(tny)); } N--; dst[x,fy] = src[x,y]; ny--; } } else {break;} } } } } else { for (int y = 0; y < h; y++) { if (IsCancelRequested) return; nx = 0; if (rowNonZeroAlphas[y] != 0) { N=rowNonZeroAlphas[y]; tx = w - N ; nx+=(int)(tx*position); for (int x = 0; x < w; x++) { if (N != 0) { if (src[x,y].A >= alpha_threshold) { tnx = influence_factor * (double)(nx) + invert_factor*(double)(x); if (position == 0) { fx=(int)(Math.Ceiling(tnx)); } else { fx=(int)(Math.Floor(tnx)); } N--; dst[fx,y] = src[x,y]; nx++; } } else {break;} } } } } } Edited May 12, 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. Link to comment Share on other sites More sharing options...
MJW Posted May 12, 2020 Share Posted May 12, 2020 One thing I noticed is that in PreRender you have: dst[x,y]=ColorBgra.FromBgra(0,0,0,0); I don't think that's kosher. As far as I know, you can only write to the destination buffer in Render, and then only within the Rectangle-Of-Interest. Quote Link to comment Share on other sites More sharing options...
Reptillian Posted May 12, 2020 Share Posted May 12, 2020 (edited) 6 minutes ago, MJW said: One thing I noticed is that in PreRender you have: dst[x,y]=ColorBgra.FromBgra(0,0,0,0); I don't think that's kosher. As far as I know, you can only write to the destination buffer in Render, and then only within the Rectangle-Of-Interest. Then, that must be part of the problem. I wanted to clear dst surface to zero as I noticed problem without doing that. The rectangle of interest is another thing that should have worked, and I checked with G'MIC-QT version of the filter, and checked the numbers of non-zero alpha between the shifted version and the non-shifted version. The expected result is exactly like the G'MIC-QT version. The code should be identical now. So, I'm lost there too. Edited May 12, 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. Link to comment Share on other sites More sharing options...
MJW Posted May 12, 2020 Share Posted May 12, 2020 Also, for (int x = 0; x < w; x++) { int nonZeroAlphaCount = 0; for (int y = 0; y < h; y++) { if (src[x,y].A >= alpha_threshold) {nonZeroAlphaCount++;} columnNonZeroAlphas[x] = nonZeroAlphaCount; //dst[x,y]=ColorBgra.FromBgra(0,0,0,0); } } Would be better as: for (int x = 0; x < w; x++) { int nonZeroAlphaCount = 0; for (int y = 0; y < h; y++) { if (src[x,y].A >= alpha_threshold) {nonZeroAlphaCount++;} //dst[x,y]=ColorBgra.FromBgra(0,0,0,0); } columnNonZeroAlphas[x] = nonZeroAlphaCount; } The point of using a local variable to accumulate the count is to avoid an array index. It's probably not worth the effort, and could be the simpler: for (int x = 0; x < w; x++) { int nonZeroAlphaCount = 0; for (int y = 0; y < h; y++) { if (src[x,y].A >= alpha_threshold) columnNonZeroAlphas[x]++; //dst[x,y]=ColorBgra.FromBgra(0,0,0,0); } } Quote Link to comment Share on other sites More sharing options...
MJW Posted May 12, 2020 Share Posted May 12, 2020 16 minutes ago, Reptillian said: Then, that must be part of the problem. I wanted to clear dst surface to zero as I noticed problem without doing that. Assuming dst can't be written in PreRender() (as I believe it can't), you've got to figure out a way to do it in Render(). It that's impossible, you need to use an auxiliary surface, do the rendering to it in PreRender(), and copy the results to dst in Render(). That's not ideal, but it's necessary for algorithms that only go in the source-to-destination direction; that is, algorithms where you can't take the destination coordinates, and figure out what color should be there. Quote Link to comment Share on other sites More sharing options...
Reptillian Posted May 12, 2020 Share Posted May 12, 2020 Just now, MJW said: Assuming dst can't be written in PreRender, you've got to figure out a way to do it in Render. It that's impossible, you need to use an auxiliary surface, do the rendering to it in PreRender, and cop the resuts to dst in Render. That's not ideal, but it's necessary for algorithms that only go in the source-to-destination direction; that is, algorithms where you can't take the destination coordinates, and figure out what color should be there. In other words, I have to start over again. Okay, I'll attempt that some time later. 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. Link to comment Share on other sites More sharing options...
null54 Posted May 12, 2020 Share Posted May 12, 2020 21 minutes ago, MJW said: As far as I know, you can only write to the destination buffer in Render, and then only within the Rectangle-Of-Interest. You can write to the destination buffer in both PreRender and Render, but you have to restrict your writes to the selection bounds in both cases. Writing outside of the selection breaks the undo command. 2 minutes ago, MJW said: It that's impossible, you need to use an auxiliary surface, do the rendering to it in PreRender, and cop the resuts to dst in Render. That's not ideal, but it's necessary for algorithms that only go in the source-to-destination direction; that is, algorithms where you can't take the destination coordinates, and figure out what color should be there. After looking at the code, that is what I would suggest. I will test that after I update CodeLab. 1 Quote Plugin Pack | PSFilterPdn | Content Aware Fill | G'MIC | Paint Shop Pro Filetype | RAW Filetype | WebP Filetype The small increase in performance you get coding in C++ over C# is hardly enough to offset the headache of coding in the C++ language. ~BoltBait Link to comment Share on other sites More sharing options...
MJW Posted May 12, 2020 Share Posted May 12, 2020 14 minutes ago, null54 said: You can write to the destination buffer in both PreRender and Render, but you have to restrict your writes to the selection bounds in both cases. Writing outside of the selection breaks the undo command. I didn't know that. Or if I knew it at one time, I'd forgotten it. In the plugin under discussion, I doubt writing to dst in PreRender() makes sense, anyhow. If the algorithm itself can be done in Render(), so can the clears. I doubt the clears in PreRender() even make sense. I bet they're just a band aid that reduces what ever problem Reptillian is seeing. Quote Link to comment Share on other sites More sharing options...
MJW Posted May 12, 2020 Share Posted May 12, 2020 18 minutes ago, Reptillian said: In other words, I have to start over again. Okay, I'll attempt that some time later. Not really start over. It would mostly be a matter of moving code from one routine to another. I wish I understood better what the code is doing; but I have great difficulty reading poorly-formatted code. (In fact, I have difficulty reading code not formatted in by preferred indentation style.) Quote Link to comment Share on other sites More sharing options...
BoltBait Posted May 12, 2020 Share Posted May 12, 2020 19 minutes ago, null54 said: You can write to the destination buffer in ...PreRender Don't do that. I used to think it was ok. Now, I don't. Currently CodeLab allows you do design plugins this way using the File > New templates... I will be correcting this for the next release. Do not use DST as another scratch surface. Stuff doesn't work right when you do this. 1 Quote Download: BoltBait's Plugin Pack | CodeLab | and a Free Computer Dominos Game Link to comment Share on other sites More sharing options...
MJW Posted May 12, 2020 Share Posted May 12, 2020 After looking through the code more carefully, I notice: dst[fx,y] = src[x,y]; That's a sure sign the call to Render() may write outside its ROI, which shouldn't be done. Either the algorithm needs to be redone (unlikely), or you need to use an aux surface. Usually, the Render() code when using an aux surface is trivial. Inside the render loops is simply: dst[x, y] = aux[x, y]. In some cases, it's possible to save some of the computations for Render() to do. It's good to do as much in Render as possible, since it's done in parallel, where PreRender() is not. Also Render() properly updates the progress bar. Also, aux doesn't have to be an actual surface. In many cases a two-dimensional array of ColorBgras works just as well, and doesn't need to be carefully disposed of. Sometimes a 2D array of floats or ints is better, leaving it to Render() to compute the color from the value in the array. For this algorithm, it could be an array of 2D indexes that tell where in the source buffer the proper color is located. (That's just an example, not a recommendation.) Quote Link to comment Share on other sites More sharing options...
Reptillian Posted May 13, 2020 Share Posted May 13, 2020 (edited) @MJW Your solution worked! Releasing the code here for testing purpose. // Name: Axis-Based Shift Grouped Pixel to Boundary // Submenu: Effects / Distortion // Author: Reptorian // Title: Axis-Based Shift Grouped Pixel to Boundary // Version: 1.0 // Desc: Extended version of Gravity by MadJik. Converted from G'MIC-QT rep_sptbwgp cli filter which is also created by Reptorian. // Keywords: Gravity // URL: https://forums.getpaint.net/profile/85868-reptillian/ // Help: #region UICode DoubleSliderControl positionperc = -100; // [-100,100] Position of Pixels (%) DoubleSliderControl influenceperc = 100; // [0,100] Influence Factor (%) IntSliderControl alpha_threshold = 255; // [1,255] Alpha Threshold ListBoxControl axis = 1; // Axis|Horizontal|Vertical #endregion int[] rowNonZeroAlphas = null; int[] columnNonZeroAlphas = null; ColorBgra[,] altsrf = null; void PreRender(Surface dst, Surface src) { int w=src.Width,h=src.Height; columnNonZeroAlphas = new int[w];rowNonZeroAlphas = new int[h]; altsrf = new ColorBgra[w,h]; int non_alpha_count = 0; int tx,ty,nx,ny,fx,fy,N; double tny,tnx; double position = (positionperc / 100 + 1) / 2; double influence_factor = influenceperc / 100; double invert_factor = 1 - influence_factor; if (axis==1) { for (int x = 0 ; x < w ; x++) { non_alpha_count = 0 ; for (int y = 0; y < h; y++){if (src[x,y].A >= alpha_threshold){non_alpha_count++;}} columnNonZeroAlphas[x] = non_alpha_count ; } for (int x = 0 ; x < w ; x++) { ny = h - 1; if (columnNonZeroAlphas[x] != 0) { N = columnNonZeroAlphas[x]; ty = h - N; ny-=(int)(Math.Round(ty * position)); for (int y = h - 1 ; y >= 0 ; y--) { if (N != 0) { if (src[x,y].A >= alpha_threshold) { tny = influence_factor * (double)(ny) + invert_factor * (double)(y); if (position == 1) { fy = (int)(Math.Floor(tny)) ; } else { fy = (int)(Math.Ceiling(tny)) ; } N--; altsrf[x,fy] = src[x,y] ; ny--; } } else {break;} } } } } else { for (int y = 0 ; y < h ; y++) { non_alpha_count = 0 ; for (int x = 0; x < w; x++){if (src[x,y].A >= alpha_threshold){non_alpha_count++;}} rowNonZeroAlphas[y] = non_alpha_count ; } for (int y = 0 ; y < h ; y++) { nx = 0; if (rowNonZeroAlphas[y] != 0) { N = rowNonZeroAlphas[y]; tx = w - N; nx+=(int)(Math.Round(tx * position)); for (int x = 0 ; x < w ; x++) { if (N != 0) { if (src[x,y].A >= alpha_threshold) { tnx = influence_factor * (double)(nx) + invert_factor * (double)(x); if (position == 1) { fx = (int)(Math.Ceiling(tnx)) ; } else { fx = (int)(Math.Floor(tnx)) ; } N--; altsrf[fx,y] = src[x,y] ; nx++; } } else {break;} } } } } } void Render(Surface dst, Surface src, Rectangle rect) { Rectangle selection = EnvironmentParameters.SelectionBounds; for (int y = rect.Top; y < rect.Bottom; y++) { if (IsCancelRequested) return; for (int x = rect.Left; x < rect.Right; x++) { dst[x,y] = altsrf[x,y] ; } } } Edited May 13, 2020 by Reptillian 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. Link to comment Share on other sites More sharing options...
toe_head2001 Posted May 13, 2020 Share Posted May 13, 2020 4 hours ago, null54 said: Writing outside of the selection breaks the undo command. That was fixed in paint.net 4.1.6. Obviously, writing outside of the selection is still a bad practice, and just wastes compute resources. 1 Quote (September 25th, 2023) Sorry about any broken images in my posts. I am aware of the issue. My Gallery | My Plugin Pack Layman's Guide to CodeLab Link to comment Share on other sites More sharing options...
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.