Is it possible to modify a part of an SDL_Texture's alpha value

I am fairly new to SDL and would like to know if there is a function in SDL or its related libraries where I can change only a part of an SDL_Texture’s alpha value without changing the entire texture’s alpha value. Looking at the Lazy Foo tutorials, I know that you can alpha blend an entire texture using SDL_SetTextureAlphaMod(SDL_Texture* texture,Uint8 alpha) but I would like to know if I can access a region of pixels from the texture and modify its alpha values while keeping the rest of the texture’s pixels alpha values unchanged.

My goal is to have different alpha values assigned to each region of my Sprite Sheet Class where each region is defined as an SDL_Rect struct.

Some help or some guidance in the right direction will be much appreciated. Thanks!

You can indeed change the alpha value of a texture. You shouldn’t do it directly on a SDL_Texture though, since it’s costly to do operations on an SDL_Texture. What you should do instead is create a SDL_Surface containing the image that you want to load. Then loop through the surface’ pixels and change the alpha value on those pixels that you wish to change. After everything is done, you can create the final texture by calling SDL_CreateTextureFromSurface().

Example code below:

[details=Click here to show/hide the code] SDL_Color GetPixelColor(const SDL_Surface* pSurface, const int X, const int Y)
{
const int Bpp = pSurface->format->BytesPerPixel;
const Uint8* pPixel = (Uint8*)pSurface->pixels + Y * pSurface->pitch + X * Bpp;
const Uint32 PixelColor = (Uint32)pPixel;

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

	SDL_GetRGBA(PixelColor, pSurface->format, &Color.r, &Color.g, &Color.b, &Color.a);

	return Color;
}

void SetPixelColor(SDL_Surface* pSurface, int X, int Y, Uint32 Pixel)
{
	Uint32* pPixels = (Uint32*)pSurface->pixels;

	pPixels[(Y * pSurface->w) + X] = Pixel;
}

bool Create(void)
{
	// Create two surfaces with the same texture in it that we can render and compare
	SDL_Surface* pSurface1 = CreateSurface("Data/Textures/Texture.png");
	SDL_Surface* pSurface2 = CreateSurface("Data/Textures/Texture.png");

	if(!pSurface1) return false;
	if(!pSurface2) return false;

	const int SurfaceWidth	= pSurface2->w;
	const int SurfaceHeight	= pSurface2->h;

	// Loop through the second surface' pixel data
	for(int i = 0; i < SurfaceHeight; ++i)
	{
		for(int j = 0; j < SurfaceWidth; ++j)
		{
			const SDL_Color PixelColor = GetPixelColor(pSurface2, j, i);

			int AlphaValue = PixelColor.a;

			// Set the alpha value of the second surface' upper left region to 16, the lower right region to 128 and let the rest of the surface' pixel values be as they are
			     if(i < (SurfaceHeight / 2) && j < (SurfaceWidth / 2)) AlphaValue = 16;
			else if(i > (SurfaceHeight / 2) && j > (SurfaceWidth / 2)) AlphaValue = 128;

			const Uint32 NewPixelValue = SDL_MapRGBA(pSurface2->format, PixelColor.r, PixelColor.g, PixelColor.b, AlphaValue);

			if(SDL_MUSTLOCK(pSurface2))
				SDL_LockSurface(pSurface2);

			SetPixelColor(pSurface2, j, i, NewPixelValue);

			if(SDL_MUSTLOCK(pSurface2))
				SDL_UnlockSurface(pSurface2);
		}
	}

	// Create the final textures
	SDL_Texture* pTexture1 = SDL_CreateTextureFromSurface(pRenderer, pSurface1);
	SDL_Texture* pTexture2 = SDL_CreateTextureFromSurface(pRenderer, pSurface2);

	if(!pTexture1) return false;
	if(!pTexture2) return false;

	SDL_SetTextureBlendMode(pTexture1, SDL_BLENDMODE_BLEND);
	SDL_SetTextureBlendMode(pTexture2, SDL_BLENDMODE_BLEND);

	return true;
}

[/details]

Result:

Hope it helps. :slight_smile:

1 Like

Thanks this helped alot, however I was able to figure out another way of changing the alpha values of each pixel. I referenced how Lazy Foo’s texture streaming was created and was also able to achieve similar results.

Result:

Glad it turned out well. :slight_smile: