How do I get the rgb values of a pixel from a given surface and x and y coordinates in SDL2?

Hi,

How do I get the rgb values of a pixel from a given surface and x and y coordinates in SDL2?

Thanks.

Hello and welcome to the forum!

You can retrieve the color/value of a specific pixel in an SDL_Surface by using the SDL_GetRGB function, or SDL_GetRGBA if the loaded image has an alpha channel (like in a PNG image for example).
Below I’ve added a code example on how such a function can be created and used.
You might have to convert between small and big endian, depending on your OS etc. So if you have any issues with the incorrect pixel color being returned from the function, small/big endian might be the issue. I’m not very good with that so I sadly can’t help you with it.

Code
SDL_Color GetPixelColor(const SDL_Surface* pSurface, const int X, const int Y)
{
	// Bytes per pixel
	const Uint8 Bpp = pSurface->format->BytesPerPixel;

	/*
	Retrieve the address to a specific pixel
	pSurface->pixels	= an array containing the SDL_Surface' pixels
	pSurface->pitch		= the length of a row of pixels (in bytes)
	X and Y				= the offset on where on the image to retrieve the pixel, (0, 0) is in the upper left corner of the image
	*/
	Uint8* pPixel = (Uint8*)pSurface->pixels + Y * pSurface->pitch + X * Bpp;

	Uint32 PixelData = *(Uint32*)pPixel;

	SDL_Color Color = {0x00, 0x00, 0x00, SDL_ALPHA_OPAQUE};

	// Retrieve the RGB values of the specific pixel
	SDL_GetRGB(PixelData, pSurface->format, &Color.r, &Color.g, &Color.b);

	return Color;
}

int main(int argc, char *argv[])
{
	SDL_Surface* pSurface = IMG_Load("Image.png");

	// Offset (4, 4) in the image/surface
	const SDL_Color Color = GetPixelColor(pSurface, 4, 4);

	if((Color.r == 255) && (Color.g == 0) && (Color.b == 0))
		std::cout << "The pixel is fully red" << std::endl;

	return 0;
}

More information: https://wiki.libsdl.org/SDL_GetRGB and https://wiki.libsdl.org/SDL_GetRGBA

Thanks for your reply.

I tried the following but I get an Access Violation error when SDL_getRGB is called.

Code extract:

function getPixel(surface: PSDL_surface; x, y: integer): UInt32;
var
bpp: integer;
p: UInt8;
begin
bpp:=surface^.format^.BytesPerPixel;
p:=UInt8(surface^.pixels+ysurface^.pitch+xbpp);
getPixel:=p;
end;

procedure splitSpriteSheet(spriteSheetNum, sheetSpritesMaxX, sheetSpritesMaxY, sheetPixelStartX, sheetPixelStartY, spriteWidth, spriteHeight,
pixelsIncrX, pixelsIncrY: word; pixelsIncrModX, pixelsIncrModY: smallInt; targetFolderName: ansistring; targetFileStartNum: word; deleteFilesStartNum, deleteFilesEndNum: smallInt; skipMiddleSprites, deleteFilesFromFolder: boolean);
var
spriteSheetSurface, spriteSheetCreatedSurface, splitSurface:PSDL_surface;
spriteSheetTexture, spriteSheetAccessTexture: PSDL_texture;
SDLRect: TSDL_rect;
sheetSpritesMaxXCnt, sheetSpritesMaxYCnt: byte;
surfacePixelX, surfacePixelY, originalPixelsIncrX, deleteFileCnt: word;
filePath, fileName, filePathAndName: ansistring;
data: UInt32;
r, g, b: PUInt8;
begin
spriteSheetSurface:=SDL_loadBMP(PChar(‘spr4\sprite sheets\spr’+fVal(spriteSheetNum)+’.spr’));
data:=getPixel(spriteSheetSurface, 1, 1);
SDL_getRGB(data, spriteSheetSurface^.format, r, g, b);
end;

Error:

An unhandled exception occurred at $6C7D7CAE :
EAccessViolation : Access violation
$6C7D7CAE
$0040F718

Check that the SDL_Surface is valid and also check that the offsets are valid, i.e that your X and Y offset values aren’t out of the pixel array’s bounds.

The surface is valid. Calling SDL_getError right after SDL_loadBMP or before SDL_getRGB returns no error.

The x and y are literally x=1 and y=1:
data:=getPixel(spriteSheetSurface, 1, 1);
(function getPixel(surface: PSDL_surface; x, y: integer): UInt32;)

The surface is an 800 x 800 .bmp sprite sheet.

Sorry, can’t help you more. No idea what might cause the error. The only thing I know is that the code is trying to access memory that isn’t valid (‘Access violation’).

Thanks. Yeah. I also tried using SDL_lockSurface eventhough that’s for when you want to change the pixel values.

I also tried creating a new surface with format RGB8888 and blitting the surface of the loaded image to the new surface and then reading the pixel from the new surface. Got the same error.

Do you know if I can talk to whoever worked on the development of the SDL_getRGB function and ask them?

The original developer of SDL is named Ryan C. Gordon, Icculus on this forum. But the library is community-developed, which means a lot of people has contributed code for it. Therefore, there might be someone else who implemented the SDL_GetRGB and SDL_GetRBGA functions.
Hopefully someone else will answer in this thread and provide help.

In the meanwhile, you should debug everything and try figuring out what’s causing the crash. Try with another image file, maybe try with another file extension etc.
I have only tried with png files together with SDL_GetRGBA and it works great for me.

Yeah I read online that SDL is developed by a community and was wondering if someone who worked on that function could help. Hopefully someone who knows why I’m getting this error can reply.

I’ve spent a few hours trying to debug this.

What I’m trying to do basically is create a procedure that will split a spritesheet into single individual sprites in their own .bmp files.

I’m getting those free spritesheets online just for the purpose of having some assets in a game I’m programming to see that the game works as intended. They will not be used in the final version of the game. The procedure already works for spritesheets that have each sprite properly aligned. The thing is not all sprites on spritesheets online are properly aligned and I wanted to be able to read the pixel rgb values on it so I could make an algorithm that would get each sprite for me. I need to be able to do this otherwise I will spend countless hours manually extracting each sprite.

For example, the spritesheet for one character has 8 directions, each with 8 animation sprites. That’s 64 individual sprites to extract. I need individual sprites because the game engine I’m programming expects each sprite to be in their own file, and they are all loaded into memory at the start of the game. Even if I don’t create individual files, I would still need to get each sprite from the sheet to display the one I need on screen, which would be the same issue, as they are not aligned properly.

I also programmed the procedure to adjust to the width between each sprite, since they are not consistent. The issue is that the width is not always increasing or decreasing. It varies between each sprite. So I’m back to having to read pixels anyway.

Until I can get the SDL_getRGB function to work I’m kind of stuck on that side of my game development. Unless I can pay a graphics designer to sit and extract each file lol, or align the sprites properly. Which would be a nightmare for that person, I’m sure.

I also started exploring whether I could do that procedure with OpenGL.

To be honest, I don’t think that’s a very good approach and that you should rethink your engine/library code design. You always wanna load as few files as possible, and loading 1 big texture atlas is better than loading 64 small textures.

Regarding the alignment of each section/frame in a texture atlas, and picking the correct frame(s) in it, you should/could have sprite/animation files.

So if you have a player actor in your game, you can have a player-related settings file that’s being loaded and parsed during player creation. That file first of all contains the filename of the texture atlas the player is supposed to use during rendering, the number of animations the player has, how many frames each animation has, where on the texture atlas each frame are located (so an X and Y offset) and finally the size of each animation frame (so a width and a height).

Do the same with all the other actors (enemies, NPC’s, animated tiles etc) in the game.

If you want to have an object that aren’t supposed to be animated, just pick 1 frame from the texture atlas and render that frame.

Perhaps but it makes no difference to the player or the graphics designer whether the program ends up using one file with all the sprites for a character or whether that is split into individual files. The graphics designer will always draw their sprites on a spritesheet and I can get my program to split that into individual sprite files. Granted it’s an additional step but all it takes is for me to run a procedure that does that and at this point it would be too much work to change that in the game engine and debug. That procedure is run only once though and never again after, since the individual files will already be split when the player gets the game.

I’m a self-taught programmer (since 1997) and when I programmed this game engine I just went with what was logical to me at the time. In my code the sprite drawn on screen is determined by a variable, and all the possible sprite file number values for a character (etc.) is contained in an array. So to me it made sense that the sprite file number would match a specific file name, rather than a spritesheet and then having to workout, while the program runs, which sprite for that sheet should be picked.

As I explained, using a spritesheet with misaligned sprites still gives me the same problem I have been trying to solve by using SDL_getRGB, whether the program works out which sprite to use from that sheet while it runs or whether it has to split that spritesheet into individual sprites first.

In any case the individual sprites are only loaded at the start of the game (when the player double-clicks on the .exe file). Then they stay in memory until the player exits the game. And also I think the memory space used by one spritesheet would be greater than individual sprites, given that a spritesheet has a lot more “white space” around each sprite on the spritesheet. It would be easier for me to explain if I could show you lol. Also, I don’t see the way I am currently doing it impacting on performance.

In any case, it works! :slight_smile: And there’s no impact on performance, nothing that will bother the player or the graphics designer. I could reprogram it the way you described, and I have thought about just that a few times, but at this point I am not willing to invest the time. This is a hobby for me, and maybe one day I can share the game with others, maybe make a little money. I already have a full-time job and reprogramming that would be a bit depressing thinking I could use the time for other things: like programming the AI behaviours.

As long as it works for you, it’s good. :slight_smile:

Great to hear that you solved the issue.

Yeah I meant the engine works but I still can’t get SDL_getRGB to work :frowning:

Oh, thought it was solved :frowning:

You might wanna message Ryan and he might be able to help you out, either with the SDL_GetRGB function or help you get in touch with the/those person(s) that actually developed it.

1 Like