Having issues with texture pixel manipulation and alpha

So what I am trying to do is manually color key a SDL_Texture. This is born out of the fact that I want to create an SDL_Texture from an SDL_Surface, but SDL_CreateTextureFromSurface() does not return a streamable texture.

So I
-load a surface and convert it to the display format
-create a streaming texture in the display format
-lock the texture to access its pixels
-memcpy the surface pixels to the texture pixels
-map the color key and the transparent pixel in the display format
-go through the texture pixels and substitute all the color key pixels with transparent pixels
-unlock the surface

So I can find the color key pixels and replace them with another color just fine. The problem is that I can’t seem to make the color transparent even though I am mapping the alpha to 0.

Here’s my code:

Code:
//The final texture
SDL_Texture* newTexture = NULL;

//Load image at specified path
SDL_Surface* loadedSurface = IMG_Load( path.c_str() );
if( loadedSurface == NULL )
{
	printf( "Unable to load image %s! SDL_image Error: %s\n", path.c_str(), IMG_GetError() );
}
else
{
	//Convert surface to display format
	SDL_Surface* formattedSurface = SDL_ConvertSurface( loadedSurface, SDL_GetWindowSurface( gWindow )->format, NULL );
	if( formattedSurface == NULL )
	{
		printf( "Unable to convert loaded surface to display format! %s\n", SDL_GetError() );
	}
	else
	{
		//Create blank streamable texture
		newTexture = SDL_CreateTexture( gRenderer, SDL_GetWindowPixelFormat( gWindow ), SDL_TEXTUREACCESS_STREAMING, formattedSurface->w, formattedSurface->h );
		if( newTexture == NULL )
		{
			printf( "Unable to create blank texture! SDL Error: %s\n", SDL_GetError() );
		}
		else
		{
			//Lock texture for manipulation
			SDL_LockTexture( newTexture, &formattedSurface->clip_rect, &mPixels, &mPitch );

			//Copy loaded/formatted surface pixels
			memcpy( mPixels, formattedSurface->pixels, formattedSurface->pitch * formattedSurface->h );

			//Get image dimensions
			mWidth = formattedSurface->w;
			mHeight = formattedSurface->h;

			//Get pixel data in editable format
			Uint32* pixels = (Uint32*)mPixels;
			int pixelCount = ( mPitch / 4 ) * mHeight;

			//Map colors
			Uint32 colorKey = SDL_MapRGB( SDL_GetWindowSurface( gWindow )->format, 0, 0xFF, 0xFF );
			Uint32 transparent = SDL_MapRGBA( SDL_GetWindowSurface( gWindow )->format, 0x00, 0xFF, 0xFF, 0x00 );
			
			//Color key pixels
			for( int i = 0; i < pixelCount; ++i )
			{
				if( pixels[ i ] == colorKey )
				{
					pixels[ i ] = transparent;
				}
			}

			//Unlock texture to update
			SDL_UnlockTexture( newTexture );
			mPixels = NULL;
		}

		//Get rid of old formatted surface
		SDL_FreeSurface( formattedSurface );
	}	
	
	//Get rid of old loaded surface
	SDL_FreeSurface( loadedSurface );
}

So what would be the best way to do manual color keying in SDL 2.0?

Alpha blending needs to be enabled explicitly.

Also are you sure it needs to be streamable? Otherwise it’d be
impossible to load the data for a new texture that isn’t streamable :stuck_out_tongue:

That doesn’t seem to be working. I tried enabling blending before the texture is locked and after and neither worked.

Code:
//The final texture
SDL_Texture* newTexture = NULL;

//Load image at specified path
SDL_Surface* loadedSurface = IMG_Load( path.c_str() );
if( loadedSurface == NULL )
{
	printf( "Unable to load image %s! SDL_image Error: %s\n", path.c_str(), IMG_GetError() );
}
else
{
	//Convert surface to display format
	SDL_Surface* formattedSurface = SDL_ConvertSurface( loadedSurface, SDL_GetWindowSurface( gWindow )->format, NULL );
	if( formattedSurface == NULL )
	{
		printf( "Unable to convert loaded surface to display format! %s\n", SDL_GetError() );
	}
	else
	{
		//Create blank streamable texture
		newTexture = SDL_CreateTexture( gRenderer, SDL_GetWindowPixelFormat( gWindow ), SDL_TEXTUREACCESS_STREAMING, formattedSurface->w, formattedSurface->h );
		if( newTexture == NULL )
		{
			printf( "Unable to create blank texture! SDL Error: %s\n", SDL_GetError() );
		}
		else
		{
			SDL_SetTextureBlendMode( newTexture, SDL_BLENDMODE_BLEND );

			//Lock texture for manipulation
			SDL_LockTexture( newTexture, &formattedSurface->clip_rect, &mPixels, &mPitch );

			//Copy loaded/formatted surface pixels
			memcpy( mPixels, formattedSurface->pixels, formattedSurface->pitch * formattedSurface->h );

			//Get image dimensions
			mWidth = formattedSurface->w;
			mHeight = formattedSurface->h;

			//Get pixel data in editable format
			Uint32* pixels = (Uint32*)mPixels;
			int pixelCount = ( mPitch / 4 ) * mHeight;

			//Map colors
			Uint32 colorKey = SDL_MapRGBA( SDL_GetWindowSurface( gWindow )->format, 0, 0xFF, 0xFF, 0xFF );
			Uint32 transparent = SDL_MapRGBA( SDL_GetWindowSurface( gWindow )->format, 0x00, 0xFF, 0xFF, 0x00 );
			
			//Color key pixels
			for( int i = 0; i < pixelCount; ++i )
			{
				if( pixels[ i ] == colorKey )
				{
					pixels[ i ] = transparent;
				}
			}

			//Unlock texture to update
			SDL_UnlockTexture( newTexture );
			mPixels = NULL;

			SDL_SetTextureBlendMode( newTexture, SDL_BLENDMODE_BLEND );
		}

		//Get rid of old formatted surface
		SDL_FreeSurface( formattedSurface );
	}	
	
	//Get rid of old loaded surface
	SDL_FreeSurface( loadedSurface );
}

//Return success
mTexture = newTexture;

Could it have to do with the display format not supporting alpha? I tried making everything SDL_PIXELFORMAT_RGBA4444, but that didn’t work either.------------------------
SDL 2.0 Tutorial (http://lazyfoo.net/tutorials/SDL/index.php) now under construction!

…well I feel stupid.

Of course a 32bit RGBA format would be SDL_PIXELFORMAT_RGBA8888 not SDL_PIXELFORMAT_RGBA4444. 3 semester of calculus, linear algebra, 2 semesters of physics and still I screw up 2nd grade math. [Embarassed]------------------------
SDL 2.0 Tutorial (http://lazyfoo.net/tutorials/SDL/index.php) now under construction!

Also check out SDL_ConvertColorkeyToAlpha() in SDL_surface.cOn Mon, Aug 19, 2013 at 9:45 PM, Lazy Foo’ wrote:

**
…well I feel stupid.

Of course a 32bit RGBA format would be SDL_PIXELFORMAT_RGBA8888 not
SDL_PIXELFORMAT_RGBA4444. 3 semester of calculus, linear algebra, 2
semesters of physics and still I screw up 2nd grade math. [image:
Embarassed]


SDL 2.0 Tutorial http://lazyfoo.net/tutorials/SDL/index.php now under
construction!


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

Hello,
maybe it’s not the best first post but i now develop applications with SDL2, very nice work and touch screen support is very cool!
I tried the lazyfoo tutorial that is very nice too.
But on the tutorial 40 I tried the code and transparency doesn’t work.
If I change the background color it still stays white for the supposed transparent pixels…
Could you please help me? I’m trying to convert my SDL 1.2 perl app in SDL 2.05 c++ app.
Thanks and have nice holidays.

Chapter 41 is working, so I will compare with the 40…