Skip to main content
GameDev.net gamedev.net
🔒 Locked

Yet another pointer hell...

Started by Lode Jul 1, 2004 at 1:57 PM 8 replies 650+ views
Original Post
Lode
Lode
I'm trying to get the color value of a pixel from an SDL surface, and I found it has to be done this way: Uint8 *p = (Uint8 *)img->pixels + y * img->pitch + x * 4; Uint32 color = *(Uint32 *)p; But whenever I want to use the variable color, the program crashes! And if I set another variable to color, it doesn't crash, but if I then use that other variable, it crashes again! What's happening here? Thanks!
DigitalDelusion
DigitalDelusion
Without seeing more code it sounds like you're reading outside the surface, check your y value.
HardDrop - hard link shell extension."Tread softly because you tread on my dreams" - Yeats
Monder
Monder
Try something like this:

Uint8 *p = (Uint8 *)img->pixels + (y * img->pitch + x) * 4;


You've gotta be careful with operator precendance. Other than that I find the following functions from the SDL docs always work:

/* * Return the pixel value at (x, y) * NOTE: The surface must be locked before calling this! */Uint32 getpixel(SDL_Surface *surface, int x, int y){    int bpp = surface->format->BytesPerPixel;    /* Here p is the address to the pixel we want to retrieve */    Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;    switch(bpp) {    case 1:        return *p;    case 2:        return *(Uint16 *)p;    case 3:        if(SDL_BYTEORDER == SDL_BIG_ENDIAN)            return p[0] << 16 | p[1] << 8 | p[2];        else            return p[0] | p[1] << 8 | p[2] << 16;    case 4:        return *(Uint32 *)p;    default:        return 0;       /* shouldn't happen, but avoids warnings */    }}/* * Set the pixel at (x, y) to the given value * NOTE: The surface must be locked before calling this! */void putpixel(SDL_Surface *surface, int x, int y, Uint32 pixel){    int bpp = surface->format->BytesPerPixel;    /* Here p is the address to the pixel we want to set */    Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;    switch(bpp) {    case 1:        *p = pixel;        break;    case 2:        *(Uint16 *)p = pixel;        break;    case 3:        if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {            p[0] = (pixel >> 16) & 0xff;            p[1] = (pixel >> 8) & 0xff;            p[2] = pixel & 0xff;        } else {            p[0] = pixel & 0xff;            p[1] = (pixel >> 8) & 0xff;            p[2] = (pixel >> 16) & 0xff;        }        break;    case 4:        *(Uint32 *)p = pixel;        break;    }}


[edit]Oh and your code will only work if the image is 32-bit colour, otherwise it will either cause a crash or give incorrect results (depending on the x and y values you put in). The above functions should work for any image.
Lode
Lode
Quote:
Original post by DigitalDelusion
Without seeing more code it sounds like you're reading outside the surface, check your y value.


Checked, and it isn't that. If I compile the code like this, it works, only if I put somewhere a line that uses the variable color, it crashes... Isn't that weird?
Lode
Lode
Quote:
Original post by Monder
Try something like this:

Uint8 *p = (Uint8 *)img->pixels + (y * img->pitch + x) * 4;


You've gotta be careful with operator precendance. Other than that I find the following functions from the SDL docs always work:

*** Source Snippet Removed ***

[edit]Oh and your code will only work if the image is 32-bit colour, otherwise it will either cause a crash or give incorrect results (depending on the x and y values you put in). The above functions should work for any image.


That what you posted is where I got my code from, the tests aren't needed, because in my case the screen is always having 32 bit color . They use return *(Uint32 *)p, because they made a function, while I use color = *(Uint32 *)p, because I don't turn it into a function. I'm really wondering why, if I do that, the program crashes if I use the variable color. This is far beyond my knowledge of pointers. If nothing works, I'm going to make it with a seperate getpixel function as well and use return *(Uint32 *)p instead, but I'll always keep wondering what happened here.

Thanks for the help :)
Monder
Monder
Yeah I just noticed that at the top of the get and set pixel functions it's the exact same thing you posted originally, and I know those work fine. When you say it crashes when you use the variable color do you mean on the Uint32 color = *(Uint32 *)p; line or some other line?
Lode
Lode
Aww, it has gotten worse!

Can somebody please explain what's going on here?

First, I type in my main function:

SDL_Surface *test;sleep(); //This function simply waits until I press a key so I know the program is working without crashing: if the program closes immediatly, it has crashed, if it "sleeps", it hasn't.


This compiles and doesn't crash.

Then, I type:

SDL_Surface *test;test=SDL_LoadBMP("omg.bmp");sleep();


And again, it compiles and works.

Then, I type:

SDL_Surface *test;test=SDL_LoadBMP("omg.bmp");int a=5;iprint(a); //iprint is a function that shows the value of a on screen.sleep();


And it compiles, and works, and shows a "5" on screen.

Then, I type:

SDL_Surface *test;test=SDL_LoadBMP("omg.bmp");int a=test->w;iprint(a); //iprint is a function that shows the value of a on screen.sleep();


And now it compiles, but CRASHES!!!! But wait, now comes the weirdest part:

SDL_Surface *test;test=SDL_LoadBMP("omg.bmp");int a=test->w;sleep();


If I compile and run this, it WORKS again WITHOUT crashing! This is exactly the same, except I don't "iprint(a)" now. If a has another value, it doesn't crash, and setting a to test->w also works, but printing this a that was set to test-> w doesn't work!

Why is this! How comes it that setting a value to the integer works, but then displaying that integer to the screen doesn't? Note that it's not only "iprint(a)" that makes it crash, I can't do ANYTHING with a without making it crash :(

Also note, that it shows exactly the same behaviour if I don't add the line "test=SDL_LoadBMP("omg.bmp");" to it, I just added that line to actually make this a surface with a certain width and height.

And finally, I can do things like "int b = a*5;" without making it crash, but then, if I use b as parameter for some function, it crashes again... Scary eh?

Thanks!
Feidias
Feidias
With SDL you can't use things like sleep() or getch(), because (I guess) SDL is expecting to have its event loop running all the time. Look for the source examples, they all have it.

Edit: Things like SDL_UpdateRect with a rectangle outside the view change other parts of the executable's code in strange ways.
DigitalDelusion
DigitalDelusion
Sounds like you're not loading that file as you should, check the return value from SDL_LoadBMP

either that or it can be a bug with linking single threaded libraries when SDL assumes multithreading
HardDrop - hard link shell extension."Tread softly because you tread on my dreams" - Yeats
Lode
Lode
My sleep(); function uses SDL events :D

DigitalDelusion: you're right, I had placed the .bmp file in the wrong folder :o

*Slaps himself with a very, very, very big trout*

I'm now implementing a test if the image actually exists in the code (simply by using the return value of the SDL_loadBMP function) and will from now on do much more error checking and such in my code :)

Thanks!

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.