How would I replace GetPixel() with something faster?
Currently I am using:
temp = GetPixel(hMonitor, 1, 1);
if (pixelArray[0] != temp)
{
pixelArray[0] = temp;
counter++;
}
Above code is just a simplified example.
This is contained in a for loop for all the pixels on the display. It compares one pixel (temp) against the previous array's pixel (pixelArray). If it has changed, then replace it. How-ever I am finding that using GetPixel() for every pixel on the display takes a long time.
I have been reading other questions of a similar nature such as:
Fastest method of screen capturing
Get Pixel color fastest way?
...but I am not sure which method is better such as GDI or DirectX nor how I would implement said methods.
Update: Windows GDI (using GetObject) to an array of the pixels is what I needed, thank you. This is much, much faster than GetPixel().
I would suggest you retrieve a pointer to the bitmap's pixel data (assuming you have a HBITMAP handle).
This is done via GetObject(), which should return you a BITMAP structure. This is the field you are interested in:
bmBits:
A pointer to the location of the bit values for the bitmap. The
bmBits member must be a pointer to an array of character (1-byte)
values.
Then you can run your checking logic per pixel on the buffers. That would be way faster from using GetPixel.
I would like to create a fake "explosion" effect in SDL. For this, I would like the screen to go from what it is currently, and fade to white.
Originally, I thought about using SDL_FillRect like so (where explosionTick is the current alpha value):
SDL_FillRect(screen , NULL , SDL_MapRGBA(screen->format , 255, 255 , 255, explosionTick ));
But instead of a reverse fading rectangle, it shows up completely white with no alpha. The other method I tried involved using a fullscreen bitmap filled with a transparent white (with an alpha value of 1), and blit it once for each explosionTick like so:
for(int a=0; a<explosionTick; a++){
SDL_BlitSurface(boom, NULL, screen, NULL);
}
But, this ended up being to slow to run in real time.
Is there any easy way to achieve this effect without losing performance? Thank you for your time.
Well, you need blending and AFAIK the only way SDL does it is with SDL_Blitsurface. So you just need to optimize that blit. I suggest benchmarking those:
try to use SDL_SetAlpha to use per-surface alpha instead of per-pixel alpha. In theory, it's less work for SDL, so you may hope some speed gain. But I never compared it and had some problem with this in the past.
you don't really need a fullscreen bitmap, just repeat a thick row. It should be less memory intensive and maybe there is a cache gain. Also you can probably fake some smoothness by doing half the lines at each pass (less pixels to blit and should still look like a global screen effect).
for optimal performance, verify that your bitmap is at the display format. Check SDL_DisplayFormatAlpha or possibly SDL_DisplayFormat if you use per-surface alpha
Using OpenGL and C++, I can draw a shape but I want to make the line of the shape thicker. How to do this?
Have a look at glLineWidth(..)
http://www.opengl.org/sdk/docs/man/xhtml/glLineWidth.xml
glLineWidth(n);
where n is the width of the line in pixels.
glLineWidth(n);
is the function but sometimes it will have no effect because of the hardware acceleration. Use software rendering first.
I wrote this function for filling closed loop, pixvali is declared globally to store the color value of the pixel where the first click will be done (inside the closed loop).
But the problem is that this recursion doesn't terminate when its first *fill(..,..)*get over, and it says stack is overflowed...
void fill(int x,int y)
{
GLfloat pixval[3];
glReadPixels(x,y,1,1,GL_RGB,GL_FLOAT,pixval);
if(pixval[0]==pixvali[0] && pixval[1]==pixvali[1] && pixval[2]== pixvali[2])
{
glBegin(GL_POINTS);
glVertex2i(x,y);
glEnd();
glFlush();
fill(x-1,y);
fill(x+1,y);
fill(x,y-1);
fill(x,y+1);
}
}
The stack overflows because you are using recursion, and the depth of the recursion is linear in the number of pixels in the shape you're filling.
It may also be that you are trying to fill the shape in the same color as it already is. That is, the current gl color is the same as pixvali. In that case, you'll get infinite recursion.
It's kind of hard to tell from the question, but my guess would be that, you begin going in a loop of pixels.
For example, think that you have only 4 pixels that you need to color (0,0), (0,1), (1,0), (1,1).
You begin coloring (0,0). Then your recursion will enter (1,0) since(-1,0) doesn't need coloring. then (0,0) again since, it's the pixel that is (x-1, y) again and so on.
You need to add some way to mark pixels that have been colored already. But that's just a guess because you can't really see what's going on outside that functions.
Not sure of the implementation details, but if the 12 byte local array is allocated on the stack (3 floats a 4 bytes each), then you have 4 bytes each for the x and y parameters, and probably four bytes for the return address. That gives at least 24 every time you recurse. That means you only need a bit more than 40'000 calls to blow through 1MB of stack space, if there's nothing else on it, which won't be true.
To put that in perspective, 43'690 pixels is only about 10% of an 800x600 display.
You need to check what pixels are you editing.
e.g. If you have an image from 0,0 to 10,10 and you edit 11,10 you will get outside of memory.
So you need to check if x,y is between the boundaries of the image.
x>=left&&x<=right&&y>=top&&y<=bottom
implement your own stack, don't use recursion for flood fill unless you are filling shapes with relatively small surface area in terms of pixels.
a typical implementation is:
Stack stack;
stack.push(firstPoint);
while(!stack.isEmpty()){
Point currentPoint= stack.pop();
//do what ever you want to do here, namely paint.
//boundary check ur surrounding points and push them in the stack if they are inbounds
}
At first glance, the algorithm looks good. I'm a bit worried about the "==" because they don't work well with float values. I suggest to use
abs(val1 - val2) < limit
instead (where limit is < 1 and > 0. Try 0.0001, for example).
To track down the bug, I suggest to add a printf() at the beginning of the function. When you see what the function tries to fill, that will help. Maybe it is stuck somewhere and calls itself again and again with the same coordinates?
Also, the stack may simple be too small for the area you try to fill. Try with a small area first, say a small rectangle only 4 by 3 pixels. Don't try to click it with the mouse but start with a known good point inside (just call fill() in your code).
Also printing the values for the color could help.
Why are you abusing OpenGL for this? What you do there is very unstable. For example the pixel read by glReadPixels will only correspond to the vertex position if a carefully chosen combination of projection and modelview matrix is used. Also every iteration of fill will do a full round trip. Just because you're using OpenGL it doesn't get magically fast.
If you want to flood fill some area in the framebuffer, readout the whole framebuffer, do the floodfill on that and push the result back to OpenGL. Also if some part of the framebuffer is occluded (by a window, or similar), those parts won't be
Now to understand why you end up in a infinite recursion. Consider this:
fill(4, 4) will call fill(5, 4) will call fill(5, 5) will call fill(4, 5) will call fill(4, 4) boom
Now you've got that test there:
if( pixval[0] == pixvali[0] &&
pixval[1] == pixvali[1] &&
pixval[2] == pixvali[2] )
Note that this evaluates true if the to be set pixel already has the target color, again winding up in a endless recursion. You should test for inequality.
Last but not least: A picture may consists of millions of pixels easily. Usual stack sizes allow only for at most a few 1000 function nesting levels, so you'll have convert your tail recursion into a iteration.
TL;DR: Don't use OpenGL for this, operate on a local buffer, use proper iteration condition test and use iteration instead of recursion (or use a functional language, then the compiler will take care of that tail recursion).
http://en.wikipedia.org/wiki/Flood_fill
I'm trying to display a picture in an openGL environment. The picture's origninal dimensions are 3648x2432, and I want to display it with a 256x384 image. The problem is, 384 is not a power of 2, and when I try to display it, it looks stretched. How can I fix that?
There's three ways of doing this that I know of -
The one Albert suggested (resize it until it fits).
Subdivide the texture into 2**n-sized rectangles, and piece them together in some way.
See if you can use GL_ARB_texture_non_power_of_two. It's probably best to avoid it though, since it looks like it's an Xorg-specific extension.
You can resize your texture so it is a power of two (skew your texture so that when it is mapped onto the object it looks correct).
ARB_texture_rectangle is probably what you're looking for. It lets you bind to GL_TEXTURE_RECTANGLE_ARB instead of GL_TEXTURE_2D, and you can load an image with non power-of-2 dimensions. Be aware that your texture coordinates will range from [0..w]x[0..h] instead of [0..1]x[0..1].
If GL_EXT_texture_rectangle is true then use GL_TEXTURE_RECTANGLE_EXT for the first param in glEnable() and GLBindTexture() calls.