View Full Version : SDL_image and bmp loading
Duane
2005.04.24, 06:25 PM
I finally managed to hack together a texture file (.h/.c), and it works fine. The only problem, as far as I can see, is that SDL-image forgets that bmps are in bgr, not RGB, and so it switches the red and blue channels (http://img.photobucket.com/albums/v441/Nayr/Picture4.jpg), which as you can imagine, is quite annoying. I would rather not convert everything over to a png, so is there a quick and easy solution to all this?
Just as I thought. I looked at the source, and guess what? NO BGR SUPPORT!
Skorche
2005.04.25, 03:21 AM
If you are using SDL, just use the format conversion functions.
SDL docWiki (http://www.libsdl.org/cgi/docwiki.cgi/SDL_5fConvertSurface)
Puzzler183
2005.04.25, 10:29 AM
Uhm, the pixel format of the surface returned indicates that it is indeed in BGR format. You should be converting it anyway since 32bpp textures are MUCH faster than 24. You probably should come up with some sort of pixel format mechanism for your own code anyway because SDL's doesn't have anything that tells OpenGL what kind of images yours is. For example, if you have 8 bits per channel and one channel, it could be GL_UMINANCE, GL_ALPHA, GL_RED, GL_GREEN, or GL_BLUE.
Duane
2005.04.27, 06:11 PM
is there anyway to figure out whether a surface is BGR or RGB? What in the SDL_PixelFormat would say so?
Puzzler183
2005.04.27, 06:33 PM
The rshift and bshift parts... Honestly though, just use the surface converter to make anything 24 bit into 32 bit RGBA because the 24 bit formats are slower. Keep 16 bit and 8 bit unpalleted things untouched though. You can determine bits per pixel with the bpp variable.
Duane
2005.04.27, 06:59 PM
meaning...
Puzzler183
2005.04.27, 07:51 PM
Ok, here is some source:
//Loads an image from a file, converting it to the appropriate format
SDL_Surface *loadImage(const char *fileName)
{
//Attempt to load the image
SDL_Surface *image = NULL;
image = IMG_Load(filename);
if (! image)
{
LOG_ERROR("Could not load image %s", fileName);
return NULL;
}
//Check the format
switch (image->format->BitsPerPixel)
{
case 8:
//It's 8 bit, do whatever
break;
case 16:
//It's 16 bit, do whatever
break;
case 24:
//It's 24 bit, so always convert (someone check my pixel format for me!)
SDL_PixelFormat format = {NULL, 32, 4, 0, 0, 0, 0, 0, 8, 16, 24, 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000, 0, 255};
SDL_Surface *temp = SDL_ConvertSurface(image, &format, SDL_SWSURFACE);
SDL_FreeSurface(image);
image = temp;
break;
case 32:
//It's 32 bit, so convert only if it's ABGR (and really, check this pixel format!)
if (image->format->rshift > image->format->bshift)
{
SDL_PixelFormat format = {NULL, 32, 4, 0, 0, 0, 0, 0, 8, 16, 24, 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000, 0, 255};
SDL_Surface *temp = SDL_ConvertSurface(image, &format, SDL_SWSURFACE);
SDL_FreeSurface(image);
image = temp;
}
break;
default:
LOG_ERROR("Unknown image format for %s", fileName);
}
return image;
}
Duane
2005.04.28, 04:26 PM
Thank you, and sorry for the trouble I caused y'all... :(
[edit]Why does it say there is a parse error before format? (SDL_PixelFormat)?
Puzzler183
2005.04.28, 04:59 PM
Oh no trouble. I didn't test that code BTW, so sorry about the syntax error - I just roughed out code and didn't test it or anything. Anyway, the fixed, syntax checked but still untested version is:
//Loads an image from a file, converting it to the appropriate format
SDL_Surface *loadImage(const char *fileName)
{
//Attempt to load the image
SDL_Surface *image = NULL;
image = IMG_Load(fileName);
if (! image)
{
LOG_ERROR("Could not load image %s", fileName);
return NULL;
}
//Check the format
switch (image->format->BitsPerPixel)
{
case 8:
//It's 8 bit, do whatever
break;
case 16:
//It's 16 bit, do whatever
break;
case 24:
//It's 24 bit, so always convert (someone check my pixel format for me!)
//Note that this scoping is used to prevent the declaration of format twice....
{
SDL_PixelFormat format = {NULL, 32, 4, 0, 0, 0, 0, 0, 8, 16, 24, 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000, 0, 255};
SDL_Surface *temp = SDL_ConvertSurface(image, &format, SDL_SWSURFACE);
SDL_FreeSurface(image);
image = temp;
break;
}
case 32:
//It's 32 bit, so convert only if it's ABGR (and really, check this pixel format!)
if (image->format->Rshift > image->format->Bshift)
{
SDL_PixelFormat format = {NULL, 32, 4, 0, 0, 0, 0, 0, 8, 16, 24, 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000, 0, 255};
SDL_Surface *temp = SDL_ConvertSurface(image, &format, SDL_SWSURFACE);
SDL_FreeSurface(image);
image = temp;
}
break;
default:
LOG_ERROR("Unknown image format for %s", fileName);
}
return image;
}
Duane
2005.04.28, 05:17 PM
hmm, not quite. You have the values wrong. You wrote it as ABGR, when it is supposed to be RGBA.
in place of the previous values, put 0xFF000000 0x00FF0000 0x0000FF00 0x000000FF
Puzzler183
2005.04.28, 05:33 PM
Oh right, you are on a Mac. Those values are little endian (so they are correct for me), however, they won't work for you. I'd suggest you use the functions in SDL_endian.h to make it all crossplatform.
Duane
2005.04.28, 05:42 PM
ahh... Cool! I was wondering what endian was for...
*goes off in search of way to use endian*
vBulletin® v3.6.8, Copyright ©2000-2008, Jelsoft Enterprises Ltd.