BoltBait Posted November 30, 2020 Share Posted November 30, 2020 BoltBait's Skew Plugin v1.0 Once installed, find Skew Horizontal and Skew Vertical in the Effects > Distort menu: Skew Vertical pretty much looks the same. Download: Until I add this to my latest plugin pack, you can download it here... Skew.zip To install this plugin, download skew.zip to your desktop, unzip all files to your desktop, and run the Install_Skew.bat file to install the Skew.dll file to your Paint.NET Effects directory. Source Code: Spoiler // Name: Skew Horizontal // Submenu: Distort // Author: BoltBait // Title: BoltBait's Skew - Horizontal v1.0 // Version: 1.0 // Desc: Skew selection // Keywords: skew // URL: https://BoltBait.com/pdn // Force Aliased Selection #region UICode IntSliderControl Amount1 = 0; // [-50,50] CheckboxControl Amount5 = true; // Fine Control CheckboxControl Amount4 = true; // Clamp to Selection CheckboxControl Amount2 = false; // Nearest Neighbor CheckboxControl Amount3 = false; // Wrapped #endregion Surface selectionSurface = null; void PreRender(Surface dst, Surface src) { // Thanks to toe_head2001 for this PreRender code // which is useful for clamping to selection Rectangle selection = this.EnvironmentParameters.SelectionBounds; if (selectionSurface == null || selectionSurface.Size != selection.Size) { selectionSurface?.Dispose(); selectionSurface = null; selectionSurface = new Surface(selection.Size); } selectionSurface.CopySurface(src, Point.Empty, selection); } void Render(Surface dst, Surface src, Rectangle rect) { int Step = Amount1; if (!Amount5) { Step *= 10; } Rectangle selection = EnvironmentParameters.SelectionBounds; float CenterY = ((selection.Bottom - selection.Top) / 2f) + selection.Top; for (int y = rect.Top; y < rect.Bottom; y++) { if (IsCancelRequested) return; float p = (CenterY - y) / (CenterY - selection.Top); for (int x = rect.Left; x < rect.Right; x++) { float XOffset = (-Step) * p; if (Amount3) { if (Amount2) { if (Amount4) { dst[x,y] = selectionSurface.GetBilinearSampleWrapped((int)(x+XOffset-selection.Left), y-selection.Top); } else { dst[x,y] = src.GetBilinearSampleWrapped((int)(x+XOffset), y); } } else { if (Amount4) { dst[x,y] = selectionSurface.GetBilinearSampleWrapped(x+XOffset-selection.Left, y-selection.Top); } else { dst[x,y] = src.GetBilinearSampleWrapped(x+XOffset, y); } } } else { if (Amount2) { if (Amount4) { dst[x,y] = selectionSurface.GetBilinearSampleClamped((int)(x+XOffset-selection.Left), y-selection.Top); } else { dst[x,y] = src.GetBilinearSampleClamped((int)(x+XOffset), y); } } else { if (Amount4) { dst[x,y] = selectionSurface.GetBilinearSampleClamped(x+XOffset-selection.Left, y-selection.Top); } else { dst[x,y] = src.GetBilinearSampleClamped(x+XOffset, y); } } } } } } Enjoy. 😎 3 2 Quote Click to play: Download: BoltBait's Plugin Pack | CodeLab | and how about a Computer Dominos Game Link to comment Share on other sites More sharing options...
docmaster Posted November 30, 2020 Share Posted November 30, 2020 Install_Skew.bat//прекрасно подошёл и открыл все ранее загруженные эффекты. Quote Link to comment Share on other sites More sharing options...
ReMake Posted November 30, 2020 Share Posted November 30, 2020 @docmaster, read the Forum Rules, please. In particular #22. And I believe that you are mistaken in claiming that Install_Skew.bat "opened all previously loaded effects". The same applies to your comment in the Water Reflection topic. @BoltBait sorry for off topic. Quote Link to comment Share on other sites More sharing options...
docmaster Posted November 30, 2020 Share Posted November 30, 2020 excuse my not literacy, it was about Mirror, which did not open immediately. And after downloading Skew v1.0 Quote Link to comment Share on other sites More sharing options...
Djisves Posted November 30, 2020 Share Posted November 30, 2020 Installed and working as expected. Thank you @BoltBait. 1 1 Quote Link to comment Share on other sites More sharing options...
Scooter Posted December 14, 2020 Share Posted December 14, 2020 BoltBait I Really like this. I don't understand it, but I do like the pretty skews and skew-ers and all. I have enclosed a mighty work of artistic doggerel, to show you. p.s. pay no attention to me, it is a great bit of program writer-ry an all. 1 Quote Scooter Age is only a number --in my case a Really BIG number, but there you have it When the prefect paint.net image is created, I will still be wondering "How they Do that?"- sigh☺️ Link to comment Share on other sites More sharing options...
mszlazak Posted April 16, 2021 Share Posted April 16, 2021 Hi Boltbait. Could you please extend the range of your skew plugin. Having a skew angle setting would be helpful. Consider the attached image. To horizontally "de-skew" this chart one needs more range than what your plugin provides. Thanks. Quote Link to comment Share on other sites More sharing options...
NSD Posted April 16, 2021 Share Posted April 16, 2021 My suggestion is to run the plugin several times, but BB may provide a better response. Quote Link to comment Share on other sites More sharing options...
BoltBait Posted April 16, 2021 Author Share Posted April 16, 2021 57 minutes ago, mszlazak said: To horizontally "de-skew" this chart one needs more range than what your plugin provides. Could you show me what you're trying to accomplish? (Even a rough sketch would be fine.) Quote Click to play: Download: BoltBait's Plugin Pack | CodeLab | and how about a Computer Dominos Game Link to comment Share on other sites More sharing options...
Reptillian Posted April 16, 2021 Share Posted April 16, 2021 (edited) She want to define the skew based on angle (I think that is what she wants). You can actually find the skew displacement at the end points based on angle by this formula (for horizontal skew): #hh is Height - 1 or end y indice# const dist=hh/2*tan(ang); Edited April 16, 2021 by Reptillian Quote G'MIC Filter Developer Link to comment Share on other sites More sharing options...
mszlazak Posted April 16, 2021 Share Posted April 16, 2021 (edited) On 4/16/2021 at 10:22 AM, BoltBait said: C Edited April 18, 2021 by mszlazak Silly response on my part. Quote Link to comment Share on other sites More sharing options...
Ego Eram Reputo Posted April 17, 2021 Share Posted April 17, 2021 10 hours ago, mszlazak said: To horizontally "de-skew" this chart one needs more range than what your plugin provides. I'm not seeing a problem with your chart. Are you seeing an optical illusion that bends the top of the chart downwards? I tried drawing a purple rectangle around the chart, and it seems to be orthogonal (which actually surprised me). 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 Link to comment Share on other sites More sharing options...
mszlazak Posted April 18, 2021 Share Posted April 18, 2021 On 4/16/2021 at 10:22 AM, BoltBait said: Could you show me what you're trying to accomplish? (Even a rough sketch would be fine.) I had to uncheck your "Fine control" to get the extent of horizontal skewing i needed. Here are the before and after pictures. For example, the red dots should be vertical and all at the 2e-17 V/NBC value afterwards. Quote Link to comment Share on other sites More sharing options...
mszlazak Posted April 19, 2021 Share Posted April 19, 2021 On 4/16/2021 at 10:22 AM, BoltBait said: Could you show me what you're trying to accomplish? (Even a rough sketch would be fine.) Addendum to my last post. I forgot to mention a request that would be helpful to control skewing. Would you consider a skew angle input since your slider scale doesn't seem to be in degree/radian units and allows decimals for finer control of angles? One could skew these curve traces to a better precision needed to extract data points from the curve with extraction software (e.g. webplotdigitizer) that is orthogonal axis based. There are probably other use cases besides this but that is currently mine. Thanks. Quote Link to comment Share on other sites More sharing options...
Reptillian Posted April 19, 2021 Share Posted April 19, 2021 (edited) 1 hour ago, mszlazak said: Addendum to my last post. I forgot to mention a request that would be helpful to control skewing. Would you consider a skew angle input since your slider scale doesn't seem to be in degree/radian units and allows decimals for finer control of angles? One could skew these curve traces to a better precision needed to extract data points from the curve with extraction software (e.g. webplotdigitizer) that is orthogonal axis based. There are probably other use cases besides this but that is currently mine. Thanks. I'm actually working on porting my gmic skew filter into skew plugin using @BoltBait original code as a starting point. That filter has angle input. EDIT: I got something here though I don't know how to work with this too well. Maybe the author will improve this code. Spoiler // Name: Skew Horizontal // Submenu: Distort // Author: BoltBait // Title: BoltBait's Skew - Horizontal v1.0 // Version: 1.0 // Desc: Skew selection // Keywords: skew // URL: https://BoltBait.com/pdn // Force Aliased Selection #region UICode DoubleSliderControl degree = 0; // [-89.99,89.99] Angle DoubleSliderControl d_position = 50; // [0,100] Position(%) CheckboxControl selection_clamp = true; // Clamp to Selection CheckboxControl nearest_mode = false; // Nearest Neighbor CheckboxControl wraparound_mode = false; // Wrapped #endregion Surface selectionSurface = null; void PreRender(Surface dst, Surface src) { // Thanks to toe_head2001 for this PreRender code // which is useful for clamping to selection Rectangle selection = this.EnvironmentParameters.SelectionBounds; if (selectionSurface == null || selectionSurface.Size != selection.Size) { selectionSurface?.Dispose(); selectionSurface = null; selectionSurface = new Surface(selection.Size); } selectionSurface.CopySurface(src, Point.Empty, selection); } void Render(Surface dst, Surface src, Rectangle rect) { double ang = ( degree / 180 ) * Math.PI; float position = (float)(d_position / 100); Rectangle selection = EnvironmentParameters.SelectionBounds; int sel_diff = selection.Bottom - selection.Top ; float sel_py = selection.Top * (1 - position) + selection.Bottom * position; double sel_dist = (double)(sel_diff) * Math.Tan(ang); int rect_diff = rect.Bottom - rect.Top; float rect_py = rect.Top * (1 - position) + rect.Bottom * position ; double rect_dist = (double)(rect_diff) * Math.Tan(ang); for (int y = rect.Top; y < rect.Bottom; y++) { if (IsCancelRequested) return; float sel_pos = (y - sel_py) / (float) (sel_diff); float sel_off = sel_pos * (float)(sel_dist) ; float rect_pos = (y - rect_py) / (float) (rect_diff); float rect_off = rect_pos * (float)(rect_dist) ; for (int x = rect.Left; x < rect.Right; x++) { if (wraparound_mode) { if (nearest_mode) { if (selection_clamp) { dst[x,y] = selectionSurface.GetBilinearSampleWrapped((int)(x+sel_off-selection.Left), y-selection.Top); } else { dst[x,y] = src.GetBilinearSampleWrapped((int)(x+rect_off), y); } } else { if (selection_clamp) { dst[x,y] = selectionSurface.GetBilinearSampleWrapped(x+sel_off-selection.Left, y-selection.Top); } else { dst[x,y] = src.GetBilinearSampleWrapped(x+rect_off, y); } } } else { if (nearest_mode) { if (selection_clamp) { dst[x,y] = selectionSurface.GetBilinearSampleClamped((int)(x+sel_off-selection.Left), y-selection.Top); } else { dst[x,y] = src.GetBilinearSampleClamped((int)(x+rect_off), y); } } else { if (selection_clamp) { dst[x,y] = selectionSurface.GetBilinearSampleClamped(x+sel_off-selection.Left, y-selection.Top); } else { dst[x,y] = src.GetBilinearSampleClamped(x+rect_off, y); } } } } } } Edited April 19, 2021 by Reptillian Quote G'MIC Filter Developer Link to comment Share on other sites More sharing options...
mszlazak Posted April 19, 2021 Share Posted April 19, 2021 3 hours ago, Reptillian said: I'm actually working on porting my gmic skew filter into skew plugin using @BoltBait original code as a starting point. That filter has angle input. EDIT: I got something here though I don't know how to work with this too well. Maybe the author will improve this code. Reveal hidden contents // Name: Skew Horizontal // Submenu: Distort // Author: BoltBait // Title: BoltBait's Skew - Horizontal v1.0 // Version: 1.0 // Desc: Skew selection // Keywords: skew // URL: https://BoltBait.com/pdn // Force Aliased Selection #region UICode DoubleSliderControl degree = 0; // [-89.99,89.99] Angle DoubleSliderControl d_position = 50; // [0,100] Position(%) CheckboxControl selection_clamp = true; // Clamp to Selection CheckboxControl nearest_mode = false; // Nearest Neighbor CheckboxControl wraparound_mode = false; // Wrapped #endregion Surface selectionSurface = null; void PreRender(Surface dst, Surface src) { // Thanks to toe_head2001 for this PreRender code // which is useful for clamping to selection Rectangle selection = this.EnvironmentParameters.SelectionBounds; if (selectionSurface == null || selectionSurface.Size != selection.Size) { selectionSurface?.Dispose(); selectionSurface = null; selectionSurface = new Surface(selection.Size); } selectionSurface.CopySurface(src, Point.Empty, selection); } void Render(Surface dst, Surface src, Rectangle rect) { double ang = ( degree / 180 ) * Math.PI; float position = (float)(d_position / 100); Rectangle selection = EnvironmentParameters.SelectionBounds; int sel_diff = selection.Bottom - selection.Top ; float sel_py = selection.Top * (1 - position) + selection.Bottom * position; double sel_dist = (double)(sel_diff) * Math.Tan(ang); int rect_diff = rect.Bottom - rect.Top; float rect_py = rect.Top * (1 - position) + rect.Bottom * position ; double rect_dist = (double)(rect_diff) * Math.Tan(ang); for (int y = rect.Top; y < rect.Bottom; y++) { if (IsCancelRequested) return; float sel_pos = (y - sel_py) / (float) (sel_diff); float sel_off = sel_pos * (float)(sel_dist) ; float rect_pos = (y - rect_py) / (float) (rect_diff); float rect_off = rect_pos * (float)(rect_dist) ; for (int x = rect.Left; x < rect.Right; x++) { if (wraparound_mode) { if (nearest_mode) { if (selection_clamp) { dst[x,y] = selectionSurface.GetBilinearSampleWrapped((int)(x+sel_off-selection.Left), y-selection.Top); } else { dst[x,y] = src.GetBilinearSampleWrapped((int)(x+rect_off), y); } } else { if (selection_clamp) { dst[x,y] = selectionSurface.GetBilinearSampleWrapped(x+sel_off-selection.Left, y-selection.Top); } else { dst[x,y] = src.GetBilinearSampleWrapped(x+rect_off, y); } } } else { if (nearest_mode) { if (selection_clamp) { dst[x,y] = selectionSurface.GetBilinearSampleClamped((int)(x+sel_off-selection.Left), y-selection.Top); } else { dst[x,y] = src.GetBilinearSampleClamped((int)(x+rect_off), y); } } else { if (selection_clamp) { dst[x,y] = selectionSurface.GetBilinearSampleClamped(x+sel_off-selection.Left, y-selection.Top); } else { dst[x,y] = src.GetBilinearSampleClamped(x+rect_off, y); } } } } } } Great! Also notice that when i skewed my original picture, the plugin did not enlarge the size of the resulting image automatically but instead cropped off parts of the curves on the right. Maybe an automatic enlargement option would be handy. Thanks. Quote Link to comment Share on other sites More sharing options...
Reptillian Posted April 19, 2021 Share Posted April 19, 2021 13 minutes ago, mszlazak said: Great! Also notice that when i skewed my original picture, the plugin did not enlarge the size of the resulting image automatically but instead cropped off parts of the curves on the right. Maybe an automatic enlargement option would be handy. Thanks. That's not possible with PDN. Also skewing with a large angle means that the enlarged picture would very big easily. If using 80 degree, the enlarged picture would add 5k to both side for 1k picture. Quote G'MIC Filter Developer Link to comment Share on other sites More sharing options...
mszlazak Posted April 20, 2021 Share Posted April 20, 2021 (edited) 10 hours ago, Reptillian said: That's not possible with PDN. Also skewing with a large angle means that the enlarged picture would very big easily. If using 80 degree, the enlarged picture would add 5k to both side for 1k picture. To bad about the PDN. I would imagine that even a limited enlargement would still help in a lot of cases. Anyway, thanks for your update and look forward to using the upgrade. Edited April 20, 2021 by mszlazak Quote Link to comment Share on other sites More sharing options...
midora Posted April 20, 2021 Share Posted April 20, 2021 There is no direct way to do it but the enlarged result could be saved on the clipboard or in a file. You may have look how the Spirit Level plugin handles the case that after rotating parts of the image are outside of the surface. Quote 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.