Jump to content

How to loop over all sourcepixels?


Recommended Posts

Hi,

for my plugin I need the min- and maxvalues of R,G,B, so I need to loop over the whole source.

How do I do that? The render-function seems to be called often and srcArgs.Surface seems to contain only the current tile.

I tried this, but this is very slow and crashes:

           for (int y = 0; y < srcArgs.Bitmap.Height; ++y)
           {
               for (int x = 0; x < srcArgs.Bitmap.Width; ++x)
               {
                   r = srcArgs.Bitmap.GetPixel(x, y).R;
                   g = srcArgs.Bitmap.GetPixel(x, y).G;
                   b = srcArgs.Bitmap.GetPixel(x, y).B;
                   if (r < minR)
                       {
                           minR = r;
                       }
                       if (g < minG)
                       {
                           minG = g;
                       }
                       if (b < minB)
                       {
                           minB = b;
                       }
                       if (r > maxR)
                       {
                           maxR = r;
                       }
                       if (g > maxG)
                       {
                           maxG = g;
                       }
                       if (b > maxB)
                       {
                           maxB = b;
                       }
               }
           }

And if I'm right with my tile-suspicion, it would be kinda unessessary to determine the min- and maxvalues every time render is called. Is there any way to do this only once?

//Edit:

Ok, found a way to actually debug some values within a dll, sry, C#-beginner.

render() is actually called ca a million times. Each time the srcArgs.Surface has the same width and height as the original image. This is weird because it means tiles seems not the reason for the many calls?

//Edit2:

"Solved" it now with some private class variables and a flag which indicates, whether it is the first call of render. Kinda ugly though. :/

Link to comment
Share on other sites

Put the part of the code that you only want to execute once in the "OnSetRenderInfo" method (instead of the "OnRender" method). OnSetRenderInfo only executes once per render (before OnRender starts getting called), whereas OnRender executes multiple times per render. Save the max values at the module level, and use the values in OnRender.

Total hack.

Link to comment
Share on other sites

Instead of looping through the whole image each time Render is called, you should only loop through the pixels passed by the array of Rectangles passed to the method. Otherwise, you're processing the entire image hundreds of times.

Put the part of the code that you only want to execute once in the "OnSetRenderInfo" method (instead of the "OnRender" method). OnSetRenderInfo only executes once per render (before OnRender starts getting called), whereas OnRender executes multiple times per render. Save the max values at the module level, and use the values in OnRender.

Don't do that unless you absolutely must. It's not multi-threaded. Render is automatically multithreaded, and will give better performance.

xZYt6wl.png

ambigram signature by Kemaru

[i write plugins and stuff]

If you like a post, upvote it!

Link to comment
Share on other sites

Instead of looping through the whole image each time Render is called, you should only loop through the pixels passed by the array of Rectangles passed to the method. Otherwise, you're processing the entire image hundreds of times.

Yes, that was in my original post, but I deleted it once I understood that what he is trying to do is just get the "min" and "max" rgb values from the entire image (all pixels), and he didn't want to do that for every call to OnRender, since he only needed to do that once. In other words, as you know, you are correct, and I agree.

Put the part of the code that you only want to execute once in the "OnSetRenderInfo" method (instead of the "OnRender" method). OnSetRenderInfo only executes once per render (before OnRender starts getting called), whereas OnRender executes multiple times per render. Save the max values at the module level, and use the values in OnRender.

Don't do that unless you absolutely must. It's not multi-threaded. Render is automatically multithreaded, and will give better performance.

True, but this is a case where it makes much more sense to do it in the OnSetRenderInfo.

It is no better or worse, performance-wise, than trying to figure out if this is the first time you are entering the "OnRender" method and just doing it one time in that method. Either way, you are executing the code exactly once, and by doing it in the OnSetRenderInfo, you actually eliminate the need to run logic multiple times to determine whether this is the first pass in OnRender or not, so overall performance would actually be (negligably) better by doing it in OnSetRenderInfo.

The problem, however, is that it is possible that the second call to OnRender could complete before the first call has completed, because the first call will be MUCH slower since it has to iterate through the entire image. In that case, the threading model would introduce a bug that would be difficult to debug. Since his "min" and "max" values are not yet set, any "OnRender" calls that completed before the first one would have bad data, and the only fix would be to go back to using OnSetRenderInfo, or create a "hack" to delay all other threads until the first thread completes.

OnSetRenderInfo is garaunteed to complete before the first call to OnRender, so that is what I would recommend.

Total hack.

Link to comment
Share on other sites

...once I understood that what he is trying to do is just get the "min" and "max" rgb values from the entire image (all pixels), and he didn't want to do that for every call to OnRender, since he only needed to do that once.

Oh. I didn't bother reading the code... silly me.

@PhilipLB: in that case, do it in OnSetRenderInfo, as jchunn said. hehe :D

xZYt6wl.png

ambigram signature by Kemaru

[i write plugins and stuff]

If you like a post, upvote it!

Link to comment
Share on other sites

...once I understood that what he is trying to do is just get the "min" and "max" rgb values from the entire image (all pixels), and he didn't want to do that for every call to OnRender, since he only needed to do that once.

Oh. I didn't bother reading the code... silly me.

@PhilipLB: in that case, do it in OnSetRenderInfo, as jchunn said. hehe :D

Don't feel bad... I made the exact same mistake with my first (deleted) response :oops:

Total hack.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...