SDL · C++

Carregando imagens com ou sem canal alpha

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.

C++
#include <string>
#include "SDL.h"

using std::string;

class Image
{
public:
    Image();
    virtual ~Image();

    void load(const string& filename, bool transparent = true);

    operator SDL_Surface*() const
    {
        return m_pSurface;
    }

private:
    SDL_Surface* m_pSurface;
};

Vamos à implementação

C++
#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)
{
    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;
    }
}

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

Fonte arquivística

Conteúdo recuperado via Wayback Machine, captura 20081006095902.

Abrir registro original ↗

Este mesmo post já existia no antecessor skhaz.wordpress.com. A cópia foi unida a este registro canônico, sem publicar um post duplicado.

Abrir captura da fase WordPress.com ↗

Discussão preservada

2 comentários

  1. Carregando imagens com a SDL « Ponto V

    [...] BitsPerPixel: Quantidade de bits num único pixel de cor. Se só os formatos RGB e ARGB existirem em sua aplicação essa informação já será suficiente para diferenciar as duas imagens, já que um usa 24 bits por pixel e o outro 32. O uso dessa técnica pode ser vista aqui no blog do Shkaz.; [...]

  2. DarkSasori

    Legal…..
    muito interessante esse seu artigo..