geist_ Posted December 30, 2022 Share Posted December 30, 2022 int num; void Render(Surface dst, Surface src, Rectangle rect) { for (int y = rect.Top; y < rect.Bottom; y++) { for (int x = rect.Left; x < rect.Right; x++) { num++; //for every pixel in your selection, increment this num variable } } #if DEBUG Debug.WriteLine(num); #endif } If you take a look at this code, the num variable should return the amount of pixels you have selected. At first it only worked some of the time, and was confused as to why. But after some messing around I found out rect only contains the selected area visible to the user: For example in a 64x64 image: Running that code with the full image selected and with the full view of it Will return the correct number of pixels, 64 * 64 = 4096 But running the code with only a part of the image visible (while still selecting it whole): Will return the wrong number of pixels, because the effect only works on the currently visible selected area, despite still having the entire image selected. Is there a way to get around this? without using src.Bounds and forcing a single render call (in order to work with none-rectangle selections) Quote the usual Link to comment Share on other sites More sharing options...
BoltBait Posted December 30, 2022 Share Posted December 30, 2022 10 minutes ago, geist_ said: If you take a look at this code, the num variable should return the amount of pixels you have selected. Nope. It will return the number of pixels in the current ROI (rectangle of interest). Please review this: https://boltbait.com/pdn/CodeLab/help/overview.php BTW, if only part of an image is visible, the renderer will slice the image up into ROI's differently such that priority is given to the visible section of your image and those ROI's will be finished first. 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...
BoltBait Posted December 30, 2022 Share Posted December 30, 2022 12 minutes ago, geist_ said: Is there a way to get around this? Well, there could be any number of "ways around this"... we just need to know what information you want: Are you after the total number of pixels selected? Does it need to take irregular selections into account, or would an overall rectangle be ok? What is the purpose of knowing this information--how will it affect your render? etc. 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...
geist_ Posted December 30, 2022 Author Share Posted December 30, 2022 Quote BTW, if only part of an image is visible, the renderer will slice the image up into ROI's differently such that priority is given to the visible section of your image and those ROI's will be finished first. ROI visible get priority, alright, but the rest of the ROI's never get passed as rect? otherwise how can i get each pixel from the current selection? Quote the usual Link to comment Share on other sites More sharing options...
geist_ Posted December 30, 2022 Author Share Posted December 30, 2022 1 minute ago, BoltBait said: Well, there could be any number of "ways around this"... we just need to know what information you want: Are you after the total number of pixels selected? Does it need to take irregular selections into account, or would an overall rectangle be ok? What is the purpose of knowing this information--how will it affect your render? etc. 1. No 2. Yes Quote without using src.Bounds and forcing a single render call (in order to work with none-rectangle selections) 3. I want to work on CurrentPixel for every pixel in the entire selection Quote the usual Link to comment Share on other sites More sharing options...
BoltBait Posted December 30, 2022 Share Posted December 30, 2022 1 minute ago, geist_ said: ROI visible get priority, alright, but the rest of the ROI's never get passed as rect? otherwise how can i get each pixel from the current selection? You really should read all the tutorials I pointed you to above. In those tutorials, it is explained that: Your effect is run multi-threaded and each thread is given an ROI to work on. 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...
BoltBait Posted December 30, 2022 Share Posted December 30, 2022 1 minute ago, geist_ said: I want to work on CurrentPixel for every pixel in the entire selection In this case, you should run CodeLab like this: This will force your effect to run as a single thread and process the entire selection as a single ROI. 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...
geist_ Posted December 30, 2022 Author Share Posted December 30, 2022 (edited) Quote In this case, you should run CodeLab like this: This will force your effect to run as a single thread and process the entire selection as a single ROI. I already tried working with Single Render Call . It still returns an amount based off my view Edited December 30, 2022 by geist_ Quote the usual Link to comment Share on other sites More sharing options...
BoltBait Posted December 30, 2022 Share Posted December 30, 2022 Sounds like you need to move your processing into the PreRender(). You can read up on that here: https://boltbait.com/pdn/CodeLab/help/tutorial3.php and https://forums.getpaint.net/topic/32107-how-to-write-an-effect-plugin-part-7-extra-surface/ 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...
MJW Posted December 30, 2022 Share Posted December 30, 2022 3 hours ago, geist_ said: If you take a look at this code, the num variable should return the amount of pixels you have selected. It'd be simpler to multiply the width of the rectangle times its height instead of using a loop. What I think should work is to clear the count in PreRender, then in each Render call calculate its ROI rectangle size and add it into the count. However, I think you'll need to copy the pixels from src to dst in the Render calls. (I should know for sure if that's necessary, but off hand, I don't.) You can do the whole thing in PreRender, but it's a little more complicated, since you either have to test each pixel to see if it's selected (which is a inefficient test), or process the list of ROI rectangles. Quote Link to comment Share on other sites More sharing options...
geist_ Posted December 30, 2022 Author Share Posted December 30, 2022 Quote It'd be simpler to multiply the width of the rectangle times its height instead of using a loop. Thank you, but that isn't what i'm trying to achieve. My main question was how the Render() function was called, since every time I ran my script, the result was based off my view of the image and not the selected area. Quote the usual Link to comment Share on other sites More sharing options...
MJW Posted December 30, 2022 Share Posted December 30, 2022 7 minutes ago, geist_ said: My main question was how the Render() function was called, since every time I ran my script, the result was based off my view of the image and not the selected area. I'm not quite sure what that means (or how the method of computing the rectangle size affects it), but if you read the tutorials, you'll see how Render is called. In summary, the selected region is divided into disjoint rectangles, and Render is called for each of those rectangles. Quote Link to comment Share on other sites More sharing options...
geist_ Posted December 30, 2022 Author Share Posted December 30, 2022 4 minutes ago, MJW said: I'm not quite sure what that means (or how the method of computing the rectangle size affects it), but if you read the tutorials, you'll see how Render is called. In summary, the selected region is divided into disjoint rectangles, and Render is called for each of those rectangles. I have read the tutorials, but you seem to not have read my post? Quote the selected region is divided into disjoint rectangles, and Render is called for each of those rectangles. I am fully aware of that - however - what the tutorial doesn't mention is that, those ROI are only from the "visible" selection from the perspective of the user. Quote the usual Link to comment Share on other sites More sharing options...
MJW Posted December 30, 2022 Share Posted December 30, 2022 1 hour ago, geist_ said: I am fully aware of that - however - what the tutorial doesn't mention is that, those ROI are only from the "visible" selection from the perspective of the user. I'm pretty certain that's wrong. Your attempt at computing the selection size doesn't work with multi-processing, since multiple Render routine calls are writing to the same variable. What you're seeing is, I believe, a result of the selected canvas being processed as a single ROI in the first instance, and two ROIs in the second. If what you say were true, then running a plugin on a partially visible image wouldn't change the pixels in the non-visible region. You can easily confirm that the entire selected region -- visible or not -- is processed. (I hypothesize that when part of the image isn't visible, PDN processes the visible area first to give the user a quicker visible response.) Quote Link to comment Share on other sites More sharing options...
geist_ Posted December 30, 2022 Author Share Posted December 30, 2022 Quote Your attempt at computing the selection size doesn't work with multi-processing, since multiple Render routine calls are writing to the same variable oh so is that it? multiple threads can't write to the same variable? nvm then lol What bugs me, is that even when I tried running it with Force Single Render Call (or building it in a .dll with single render call enabled) it still called Render multiple times Quote the usual Link to comment Share on other sites More sharing options...
MJW Posted December 31, 2022 Share Posted December 31, 2022 2 hours ago, geist_ said: oh so is that it? multiple threads can't write to the same variable? They can write to the same variable, but since the variable is shared between them, and not individual to each thread, they'll write on top of each other. The value will be whatever was written last. If it were a local variable, rather than a class-level variable, each thread would have its own copy. But, of course, the variable would be lost as soon as the particular Render call exited. Quote Link to comment Share on other sites More sharing options...
MJW Posted December 31, 2022 Share Posted December 31, 2022 2 hours ago, geist_ said: What bugs me, is that even when I tried running it with Force Single Render Call (or building it in a .dll with single render call enabled) it still called Render multiple times For reasons which I do not know (though I expect they are good ones), when a plugin is called, a rendering pass is often started, then aborted, and another pass is begun. Perhaps that's what's happening. (By a rendering pass, I mean an attempt to render the full image -- the thing that happens each time a control is changed.) 1 Quote Link to comment Share on other sites More sharing options...
geist_ Posted December 31, 2022 Author Share Posted December 31, 2022 48 minutes ago, MJW said: For reasons which I do not know (though I expect they are good ones), when a plugin is called, a rendering pass is often started, then aborted, and another pass is begun. Perhaps that's what's happening. (By a rendering pass, I mean an attempt to render the full image -- the thing that happens each time a control is changed.) I'm very glad you pointed this out, my script has a Drop-Down List Box options control, and every time i change that option, it gets called with the previous option again, then with the new one. Do you happen to know a way to prevent this? perhaps @BoltBait you could know? Last question i promise Quote the usual Link to comment Share on other sites More sharing options...
Rick Brewster Posted January 5 Share Posted January 5 To count the pixels that are contained in the selection, you don't need to use the rois parameter. For a classic effect (a pre-v5.0 effect), which is what you're using, you can access all of the rectangles of the selection via this.EnvironmentParameters.GetSelectionAsPdnRegion().GetRegionScansInt() and then just do whatever you need with the list of rectangles. So do a foreach over them and add up the Width*Height or whatever (I recommend casting Width and Height to long, and summing into a long, not an int, otherwise your code will fail on larger images). For modern effects (BitmapEffect and GpuEffect in PDNv5), once CodeLab supports these you'll have a slightly different way of retrieving this, but it's fundamentally the same thing. Quote The Paint.NET Blog: https://blog.getpaint.net/ Donations are always appreciated! https://www.getpaint.net/donate.html 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.