Introdução a SDL Video

Vídeo é provavelmente a coisa mais comum para qual SDL é usado, e, este é o seu subsistema mais completo. Aqui vão alguns exemplos para demonstrar os seus fundamentos.

Iniciando o Display de Vídeo

Isto é o que quase todos os programas SDL tem que fazer, de uma maneira ou de outra.

Exemplo 2-1. Iniciando o Display de Vídeo

    SDL_Surface *screen;

    /* Inicia a biblioteca SDL */

    if( SDL_Init(SDL_INIT_VIDEO) < 0 ) {

        fprintf(stderr,"Não foi possível iniciar SDL: %s\n", SDL_GetError());

        exit(1);
    } 

    /* Limpa tudo na saída */

    atexit(SDL_Quit);
  
    /*
     * Inicia o vídeo em um modo 640x480 usando uma paleta de 8-bits,
     * requisitando uma surface de software
     */

    screen = SDL_SetVideoMode(640, 480, 8, SDL_SWSURFACE);

    if ( screen == NULL ) {
        fprintf(stderr, "Não foi possível estabelecer o modo 640x480x8: %s\n",                   SDL_GetError());

        exit(1);
    }

Iniciando o Melhor Modo de Vídeo

Se você tiver preferência por uma certa profundidade de pixels mas aceitará qualquer outra, use SDL_SetVideoMode com SDL_ANYFORMAT como mostrado abaixo. Você também pode usar SDL_VideoModeOK() achar o modo de vídeo nativo que é mais próximo para o modo que você solicita.

Exemplo 2-2. Iniciando o Melhor Modo de Vídeo

    /* Tem preferência por 8-bits, mas aceita qualquer outra profundidade */
    screen = SDL_SetVideoMode(640, 480, 8, SDL_SWSURFACE|SDL_ANYFORMAT);

    if ( screen == NULL ) {
        fprintf(stderr, "Não foi possível estabelecer o modo 640x480x8: %s\n",                      SDL_GetError());

        exit(1);
    }

    printf("Estabelecendo o modo 640x480 a %d bits-por-pixel \n",
           screen->format->BitsPerPixel);

Carregando e Mostrando um Arquivo BMP

A seguinte função carrega e mostra um arquivo BMP passado como parâmetro, desde que SDL esteja iniciada e o modo de vídeo tenha sido estabelecido.

Exemplo 2-3. Carregando e Mostrando um Arquivo BMP

void display_bmp(char *file_name)
{

    SDL_Surface *image;

    /* Carrega o arquivo BMP em uma surface */
    image = SDL_LoadBMP(file_name);

    if (image == NULL) {
        fprintf(stderr, "Não pode carregar %s: %s\n", file_name, SDL_GetError());

        return;
    }
 
    /*
     * Modos de video paletizados, terão uma paleta padrão (um cubo
     * padrão de 8*8*4 cores), mas se a imagem é paletizada também, nós podemos
     * usar aquela paleta para um melhor ajuste de cor 
     */

    if (image->format->palette && screen->format->palette) {

    SDL_SetColors(screen, image->format->palette->colors, 0,            image->format->palette->ncolors);

    }

    /* Blita na surface de vídeo */
    if(SDL_BlitSurface(image, NULL, screen, NULL) < 0)
        fprintf(stderr, "Erro blitando surface: %s\n", SDL_GetError());

     SDL_UpdateRect(screen, 0, 0, image->w, image->h);

    /* Libera a surface BMP alocada */
    SDL_FreeSurface(image);

}

Desenhando Diretamente para o Vídeo

As duas funções seguintes podem ser usadas para pegar e estabelecer pixels individuais em uma surface. Elas foram cuidadosamente escritas para trabalhar com qualquer profundidade atualmente suportada pela SDL. Lembre-se de travar a surface antes de chamá-las, e de destravá-las antes de chamar qualquer outra função da SDL.

Para converter entre valores de pixel e seus componentes vermelho, verde e azul, use SDL_GetRGB() e SDL_MapRGB().

Exemplo 2-4. getpixel()

/*
 * Retorna o valor do pixel em (x, y)
 * NOTA: A surface deve ser travada antes de chamar isto! 
 */

Uint32 getpixel(SDL_Surface *surface, int x, int y)
{
    int bpp = surface->format->BytesPerPixel;

    /* Aqui p é o endereço para o pixel que queremos recuperar */
    Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;

    switch(bpp) {

    case 1:
        return *p;

    case 2:
        return *(Uint16 *)p;

    case 3:
        if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
            return p[0] << 16 | p[1] << 8 | p[2];
        else
            return p[0] | p[1] << 8 | p[2] << 16;

    case 4:
        return *(Uint32 *)p;

    default:
        return 0;       /* não deve acontecer, mas evitamos as advertências */

    }

}

Exemplo 2-5. putpixel()

/*
 * Fixa o pixel em (x, y) para o valor passado como parâmetro 
 * NOTA: A surface deve ser travada antes de chamar isto!
 */

void putpixel(SDL_Surface *surface, int x, int y, Uint32 pixel)
{

    int bpp = surface->format->BytesPerPixel;

    /* Aqui p é o endereço para o ponteiro que queremos fixar */
    Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;

    switch(bpp) {

    case 1:
        *p = pixel;
        break;

    case 2:
        *(Uint16 *)p = pixel;
        break;

    case 3:
        if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
            p[0] = (pixel >> 16) & 0xff;
            p[1] = (pixel >> 8) & 0xff;
            p[2] = pixel & 0xff;
        } else {
            p[0] = pixel & 0xff;
            p[1] = (pixel >> 8) & 0xff;
            p[2] = (pixel >> 16) & 0xff;
        }
        break;

     case 4:
        *(Uint32 *)p = pixel;
        break;

    }

}

O seguinte código usa a função putpixel(), para colocar um pixel amarelo na metade do vídeo.

Exemplo 2-6. Usando putpixel()

  /* Código para colocar um pixel amarelo no centro do vídeo */
    int x, y;
    Uint32 yellow;

    /* Mapeia a cor amarela para este vídeo (R=0xff, G=0xFF, B=0x00)
       Nota: Se o vídeo for paletizado, você deve estabelecer a paleta primeiro.
    */

    yellow = SDL_MapRGB(screen->format, 0xff, 0xff, 0x00);
    x = screen->w / 2;
    y = screen->h / 2;

    /* Trava a tela para acessar diretamente os pixels */
    if ( SDL_MUSTLOCK(screen) ) {
        if ( SDL_LockSurface(screen) < 0 ) {
            fprintf(stderr, "Não pode travar a tela: %s\n", SDL_GetError());
            return;
        }
    }

    putpixel(screen, x, y, yellow);

    if ( SDL_MUSTLOCK(screen) ) {
        SDL_UnlockSurface(screen);
    }

    /* Atualiza apenas a parte do vídeo que modificamos */
    SDL_UpdateRect(screen, x, y, 1, 1);

    return;

SDLDoc-ptBR/Introducao_ao_Video_SDL (last edited 2008-04-17 08:18:55 by localhost)