How to change pixels using SDL?

I have a little problem: I cannot change the pixels of the SDL screen.

In particular, the following code does not work.

Uint32 * pixels = (Uint32 *) screen -> pixels; screen -> pixels = pixels; 

It compiles but shows nothing. What am I missing?

+7
source share
5 answers

I had the following functions lying around for setting pixels in SDL_Surface. There are two versions for 32-bit, 24-bit, 16-bit and 8-bit surfaces. If you just want to set one pixel, you will use regular versions. But if you want to set a bunch of pixels, first lock the surface, then you use the nolock version (called that because it does not block the surface), and then you unlock. This way, you do not repeatedly lock and unlock the surface, which is supposed to be an expensive operation, although I do not think I have ever tested it.

 void PutPixel32_nolock(SDL_Surface * surface, int x, int y, Uint32 color) { Uint8 * pixel = (Uint8*)surface->pixels; pixel += (y * surface->pitch) + (x * sizeof(Uint32)); *((Uint32*)pixel) = color; } void PutPixel24_nolock(SDL_Surface * surface, int x, int y, Uint32 color) { Uint8 * pixel = (Uint8*)surface->pixels; pixel += (y * surface->pitch) + (x * sizeof(Uint8) * 3); #if SDL_BYTEORDER == SDL_BIG_ENDIAN pixel[0] = (color >> 24) & 0xFF; pixel[1] = (color >> 16) & 0xFF; pixel[2] = (color >> 8) & 0xFF; #else pixel[0] = color & 0xFF; pixel[1] = (color >> 8) & 0xFF; pixel[2] = (color >> 16) & 0xFF; #endif } void PutPixel16_nolock(SDL_Surface * surface, int x, int y, Uint32 color) { Uint8 * pixel = (Uint8*)surface->pixels; pixel += (y * surface->pitch) + (x * sizeof(Uint16)); *((Uint16*)pixel) = color & 0xFFFF; } void PutPixel8_nolock(SDL_Surface * surface, int x, int y, Uint32 color) { Uint8 * pixel = (Uint8*)surface->pixels; pixel += (y * surface->pitch) + (x * sizeof(Uint8)); *pixel = color & 0xFF; } void PutPixel32(SDL_Surface * surface, int x, int y, Uint32 color) { if( SDL_MUSTLOCK(surface) ) SDL_LockSurface(surface); PutPixel32_nolock(surface, x, y, color); if( SDL_MUSTLOCK(surface) ) SDL_UnlockSurface(surface); } void PutPixel24(SDL_Surface * surface, int x, int y, Uint32 color) { if( SDL_MUSTLOCK(surface) ) SDL_LockSurface(surface); PutPixel24_nolock(surface, x, y, color); if( SDL_MUSTLOCK(surface) ) SDL_LockSurface(surface); } void PutPixel16(SDL_Surface * surface, int x, int y, Uint32 color) { if( SDL_MUSTLOCK(surface) ) SDL_LockSurface(surface); PutPixel16_nolock(surface, x, y, color); if( SDL_MUSTLOCK(surface) ) SDL_UnlockSurface(surface); } void PutPixel8(SDL_Surface * surface, int x, int y, Uint32 color) { if( SDL_MUSTLOCK(surface) ) SDL_LockSurface(surface); PutPixel8_nolock(surface, x, y, color); if( SDL_MUSTLOCK(surface) ) SDL_UnlockSurface(surface); } 
+18
source

Manipulating the contents of screen->pixels will change pixels with a few caveats.

First, as you showed in the code snippet, notice that screen->pixels is a pointer to the pixel data on the surface. The pixel data itself accesses the linear array from this pointer based on the width of the surface ( surface->pitch ) and the pixel size in bytes. The pixel size (aka depth) is set during initialization using SDL_SetVideoMode() and can be found in screen->format->BytesPerPixel .

It may be necessary to lock the surface before making changes.

In addition, depending on the parameters that were passed to SDL_SetVideoMode() , you may also need to call SDL_Flip() to display your changes.

A working example of pixel manipulation can be found here .


As noted in the comments, the code indicated in the question will not actually do anything visible, since no changes will be made to the pixel data.

+2
source

Adding a variant of SDL2 that controls pixels not on the surface, but in the renderer (and which does not crash if you try to manipulate pixels outside your screen, unlike previous answers)

 void putPixelRGB(SDL_Renderer* renderer, int x, int y, unsigned char r, unsigned char g, unsigned char b) { SDL_SetRenderDrawColor(renderer, (Uint8)r, (Uint8)g, (Uint8)b, 255); SDL_RenderDrawPoint(renderer, x, y); } 
+1
source

why change the pixel?

create a new surface and rect

// CODE ------------>

 SDL_Surface *screen, *PIXEL = NULL; SDL_Rect PIXELRect; PIXELRect.h=5; PIXELRect.w=5; PIXELRect.x=100; PIXELRect.y=100; screen = SDL_SetVideoMode(640, 468, 32, SDL_DOUBLEBUF | SDL_HWSURFACE | SDL_ANYFORMAT); while(running){ SDL_FillRect(screen, &PIXELRect, (#color)); } 
-one
source

You must not modify the contents of the SDL_Surface structure. If you want to copy pixels, you must malloc () some memory, and then memcpy () pixels.

-2
source

All Articles