Bug in SDL_CreateTextureFromSurface?

Hi,

I loaded an image which the pixel format is ABGR. However, it seems that when I create a texture from a surface SDL2 does not keep the format of the surface. And therefore, if I try to update it later with SDL_UpdateTexture() I get inverted red and blue channels (i.e., it seems to think the image is in ARGB format).
I had to use SDL_CreateTexture and explicitly set the format for it to work as expected.

If anybody can confirm this I will file a bug.

The code is as follows. By changing the way the texture is made, the final result changes.

Code:

#include"SDL2/SDL.h"
#include"SDL2/SDL_image.h"
#include

int main(int argc, char** argv)
{
bool quit= false;
int filter_size=2;

SDL_Event event;

SDL_Init(SDL_INIT_VIDEO);

SDL_Surface* image= IMG_Load("image3.png");
int image_height=image->h;
int image_width=image->w;
int bpp = (int) image->format->BytesPerPixel;
std::cout << "Bpp " << bpp << "Size "<< image->w << image->h << std::endl;
SDL_PixelFormat* pixel_format = image->format;
Uint32 pixelFormatEnum = pixel_format->format;
const char* surface_pixel_format = SDL_GetPixelFormatName(pixelFormatEnum);
std::cout << "Format " << surface_pixel_format << std::endl;


SDL_Window* window= SDL_CreateWindow("Convolution", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, image_width/2, image_height/2, 0);

SDL_Renderer* renderer= SDL_CreateRenderer(window, -1, 0);



SDL_Texture* texture= SDL_CreateTextureFromSurface(renderer, image);

//SDL_Texture* texture= SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ABGR8888, SDL_TEXTUREACCESS_STREAMING, image->w, image->h);


SDL_UpdateTexture(texture, NULL, image->pixels, image->pitch);

//SDL_LockTexture(texture, NULL, &image->pixels, &image->pitch);
//SDL_UnlockTexture(texture);
	
while(!quit)
{


	SDL_WaitEvent(&event);

	switch(event.type)
	{
		case SDL_QUIT:
		{
			quit=true;
		}
		break;
	}

	SDL_RenderCopy(renderer, texture, NULL, NULL);
	SDL_RenderPresent(renderer);
}

SDL_DestroyTexture(texture);
SDL_FreeSurface(image);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);

SDL_Quit();

return 0;

}

Hi,

I don’t think this is a bug: SDL_CreateTextureFromSurface() converts the
pixels to a format best suited for the renderer.

Also, note how SDL_UpdateTexture() does not take a SDL_Surface as
input, but a void pointer to “raw pixel data”.
This means the function does not “know” how to convert image surface to
the internally used format.
Maybe use SDL_QueryTexture() to get the texture’s raw format and convert
your surface to that?
(I don’t think you can expect your currently commented out code to
always work, as the render is not guaranteed to support any specific
pixelformat you might set in SDL_CreateTexture())

Cheers,
DanielOn 21.11.2016 09:06, zweifel wrote:

Hi,

I loaded an image which the pixel format is ABGR. However, it seems that
when I create a texture from a surface SDL2 does not keep the format of
the surface. And therefore, if I try to update it later with
SDL_UpdateTexture() I get inverted red and blue channels (i.e., it seems
to think the image is in ARGB format).
I had to use SDL_CreateTexture and explicitly set the format for it to
work as expected.

If anybody can confirm this I will file a bug.

The code is as follows. By changing the way the texture is made, the
final result changes.

Code:

#include"SDL2/SDL.h"
#include"SDL2/SDL_image.h"
#include

int main(int argc, char** argv)
{
bool quit= false;
int filter_size=2;

SDL_Event event;

SDL_Init(SDL_INIT_VIDEO);

SDL_Surface* image= IMG_Load(“image3.png”);
int image_height=image->h;
int image_width=image->w;
int bpp = (int) image->format->BytesPerPixel;
std::cout << "Bpp " << bpp << "Size "<< image->w << image->h <<
std::endl;
SDL_PixelFormat* pixel_format = image->format;
Uint32 pixelFormatEnum = pixel_format->format;
const char* surface_pixel_format =
SDL_GetPixelFormatName(pixelFormatEnum);
std::cout << "Format " << surface_pixel_format << std::endl;

SDL_Window* window= SDL_CreateWindow(“Convolution”,
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, image_width/2,
image_height/2, 0);

SDL_Renderer* renderer= SDL_CreateRenderer(window, -1, 0);

SDL_Texture* texture= SDL_CreateTextureFromSurface(renderer, image);

//SDL_Texture* texture= SDL_CreateTexture(renderer,
SDL_PIXELFORMAT_ABGR8888, SDL_TEXTUREACCESS_STREAMING, image->w, image->h);

SDL_UpdateTexture(texture, NULL, image->pixels, image->pitch);

//SDL_LockTexture(texture, NULL, &image->pixels, &image->pitch);
//SDL_UnlockTexture(texture);

while(!quit)
{

  SDL_WaitEvent(&event);

  switch(event.type)
  {
     case SDL_QUIT:
     {
        quit=true;
     }
     break;
  }

  SDL_RenderCopy(renderer, texture, NULL, NULL);
  SDL_RenderPresent(renderer);

}

SDL_DestroyTexture(texture);
SDL_FreeSurface(image);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);

SDL_Quit();

return 0;
}


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