Carregando imagens com ou sem canal alpha
Filed under: SDL
Muitos já devem ter passado por isso, como descobrir se uma imagem tem ou não o canal alpha (transparência), e como carregá-la corretamente. Eis aqui uma classe que se encarrega de carregar a imagem, e descobrir se tem ou não o canal alpha.
#include <string>
#include "SDL.h"
using std::string;
class Image
{
public:
Image();
virtual ~Image();
void load(const string& filename, bool transparent = true);
void close();
operator SDL_Surface*() const
{
return m_pSurface;
}
private:
SDL_Surface* m_pSurface;
};
Vamos à implementação
#include "Image.h"
Image::Image()
: m_pImage(NULL)
{
}
Image::~Image()
{
if (m_pImage != NULL) {
SDL_FreeSurface(m_pSurface);
}
}
void Image::load(const string& filename, bool transparent)
{
close();
if ((m_pSurface = IMG_Load(filename.c_str())) == NULL)
{
throw Exception("%s", IMG_GetError());
}
bool hasAlpha = false;
// Se a imagem tem 32 bits, provalvelmente
// ela tem o canal alpha, caso contrario ela
// não tem, e nem precissamos verificar.
if (m_pSurface->format->BitsPerPixel == 32)
{
// Percorremos toda a superficie da imagem
for (int i = 0; i < m_pSurface->w * m_pSurface->h; ++i)
{
Uint8 r, g, b, a;
// Mapeamos o pixel e obtemos seus
// respectivos valores em RGBA
SDL_GetRGBA(((Uint32*) m_pSurface->pixels)[i],
m_pSurface->format, &r, &g, &b, &a);
// Se o canal alpha for diferente de 255 (opaco)
// então a imagem tem trasparencia
// finalizamos o loop com o break.
if (a != 255)
{
hasAlpha = true;
break;
}
}
}
// Se a imagem tiver o canal de trasparencia
// optimizamos ela da maneira correta.
if (hasAlpha) {
temp = SDL_DisplayFormatAlpha(m_pSurface);
}
// Caso contrario, optimizamos para uma
// superficie sem alpha
else {
temp = SDL_DisplayFormat(m_pSurface);
if (transparent)
{
SDL_SetColorKey(temp, (SDL_SRCCOLORKEY | SDL_RLEACCEL | SDL_HWACCEL),
SDL_MapRGB(SDL_GetVideoSurface()->format,
255, 0, 255));
}
}
if (temp)
{
SDL_FreeSurface(m_pSurface);
m_pSurface = temp;
}
}
void Image::close()
{
if (m_pImage != NULL) {
SDL_FreeSurface(m_pSurface);
}
}
SDL_GetVideoSurface() Essa função retorna o ponteiro da superficie do video (a publica, e não a real), veja a documentação da SDL para maiores informações
Veja também
Mais detalhes da estrutura interna da SDL_Surface em SDL_Surface - Introdução detalhada, de Diogo_RBG
