We are currently migrating Bugzilla to GitHub issues.
Any changes made to the bug tracker now will be lost, so please do not post new bugs or make changes to them.
When we're done, all bug URLs will redirect to their equivalent location on the new bug tracker.

Bug 3354 - SDL_SetSurfaceBlendMode doesn't function on indexed-colour types
Summary: SDL_SetSurfaceBlendMode doesn't function on indexed-colour types
Status: NEW
Alias: None
Product: SDL
Classification: Unclassified
Component: render (show other bugs)
Version: 2.0.4
Hardware: x86_64 Windows 7
: P2 normal
Assignee: Sam Lantinga
QA Contact: Sam Lantinga
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2016-06-05 00:07 UTC by mattreecebentley
Modified: 2016-06-08 07:05 UTC (History)
1 user (show)

See Also:


Attachments
test case (1.87 KB, text/x-csrc)
2016-06-08 06:58 UTC, Sylvain
Details
input image for the test case (4.56 KB, image/png)
2016-06-08 06:59 UTC, Sylvain
Details

Note You need to log in before you can comment on or make changes to this bug.
Description mattreecebentley 2016-06-05 00:07:42 UTC
This problem occurs when you have a indexed-coloured 256-colour image with a transparency colour.

If you load the 256-colour PNG8 sprite tile into a RGBA surface, then copy each sprite from that tile to a different surface, even if you set SDL_SetSurfaceBlendMode(tiles_surface, SDL_BLENDMODE_NONE);
and
SDL_SetSurfaceBlendMode(copy_surface, SDL_BLENDMODE_NONE);

Every image after the first sprite will be overlaid on top of the original image.
In other words, it's not blanket-copying the entire sprite, it's copying all pixels *Except* the transparency colour.

So unless you use SDL_FillRect on the copy_surface, you end up with some overlaid sprites.
Comment 1 Sylvain 2016-06-05 11:13:45 UTC
I would suggest you to write a minimal test case.
Comment 2 mattreecebentley 2016-06-08 02:51:45 UTC
Haven't tested this, but should be close enough


// Create a 32-bit, alpha-channeled SDL_Surface in the appropriate endian order for the given platform:
inline SDL_Surface * create_surface(const int width, const int height)
{
	/* SDL interprets each pixel as a 32-bit number, so our masks must depend
	   on the endianness (byte order) of the machine */
	#if SDL_BYTEORDER == SDL_BIG_ENDIAN
		return SDL_CreateRGBSurface(0, width, height, 32, 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
	#else
		return SDL_CreateRGBSurface(0, width, height, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
	#endif
}



std::vector <SDL_Texture *> frames;



int add_frames_from_tile(const char *image_filename, const unsigned int number_of_frames, const unsigned int frame_width)
{
	SDL_Surface *tiles_surface = IMG_Load(image_filename);

	const int total_width = static_cast<int>(number_of_frames * frame_width);

    // Create a frame surface for copying the individual frames to:
	SDL_Surface *frame_surface = create_surface(frame_width, tiles_surface->h);
        SDL_Texture *frame;

	SDL_SetSurfaceBlendMode(tiles_surface, SDL_BLENDMODE_NONE);
	SDL_SetSurfaceBlendMode(frame_surface, SDL_BLENDMODE_NONE);
	
	SDL_Rect source_rectangle = {0, 0, static_cast<int>(frame_width), tiles_surface->h};

	for (; source_rectangle.x != total_width; source_rectangle.x += frame_width)
	{
		// Sprite tiles will be overlaid without this line:
// SDL_FillRect(frame_surface, NULL, 0x000000);
                SDL_BlitSurface(tiles_surface, &source_rectangle, frame_surface, NULL);
                frame = SDL_CreateTextureFromSurface(Renderer, frame_surface);
		frames.push_back(frame);
	}
	
	SDL_FreeSurface(tiles_surface);
	SDL_FreeSurface(frame_surface);
	return 0;
}
Comment 3 Sylvain 2016-06-08 06:58:44 UTC
Created attachment 2484 [details]
test case
Comment 4 Sylvain 2016-06-08 06:59:17 UTC
Created attachment 2485 [details]
input image for the test case
Comment 5 Sylvain 2016-06-08 07:05:46 UTC
Here's a small test case, just loading and saving surface/image.

This issue happens because the *alpha* channel of a palette surface, is in fact a color key.

So you don't have to set the "blend mode" to none, but disable the color key, then re-enable it on the output.

Since color key is color, you need to retrieve it, convert it from the input pixel_format, to the output pixel_format, to set it back. ( 


Maybe SDL_SetSurfaceBlendMode could be translated as "disable colorkey" for palette surface ? but to re-activate it, you need the explicit value.