Archive for the ‘SDL’ Category

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, &amp;r, &amp;g, &amp;b, &amp;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

Tags: , , , , ,

Permalink Comments (2) skhaz Aug 11, 2008