Sign in to follow this  
PhilipLB

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. :/

Share this post


Link to post
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.

Share this post


Link to post
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.

Share this post


Link to post
Share on other sites

I stayed with my first solution with the flag. :) A private boolean, which indicates, whether it's the first call of the render-function. If so, I loop over so whole Sourceimage to determine the min- and maxvalues of the pixels.

Share this post


Link to post
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.

Share this post


Link to post
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

Share this post


Link to post
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:

Share this post


Link to post
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.

Sign in to follow this