domingo, 4 de outubro de 2015

04 – SDL2 – Desenhando uma imagem na tela

    Agora que já sabemos como criar uma janela vamos para a próxima etapa, desenhar uma imagem na tela. Neste tutorial vamos ver como carregar um arquivo bitmap e exibido em alguma posição definida da janela do nosso programa.
    Dai você se pergunta: “Porque um bitmap e não uma imagem jpeg ou png que ocupam um espaço menor em disco?” A biblioteca SDL por si só não tem a capacidade de exibir estes tipos de imagem, para que se possa carregar outro formato é necessário utilizar uma biblioteca externa. Do mesmo criador da SDL tem a SDL_Image (https://www.libsdl.org/projects/SDL_image/), através das funções desta é possível carregar vários outros formatos além do bitmap. Existem inúmeras outras opções que pode ser usada em conjunto com a SDL a fim de dar a ela a capacidade de carregar outros tipos de imagem. Entre elas existe a FreeImage (http://freeimage.sourceforge.net/download.html) que além de expandir os formatos possui outras funções, tal como rotação, escala entre outras. Pretendo abordar esta biblioteca em um tutorial futuro. Bem, valor largar de falação e ir para o código.



#include <stdio.h> // Para a fprintf
#include <SDL2/SDL.h>


int main(int argc,char* argv[]){


    if(SDL_Init(SDL_INIT_VIDEO) !=0){
        fprintf(stderr, "\nImpossivel iniciar o video: %s\n", SDL_GetError());
        return 1;
    }

    SDL_Window* janela;
    janela = SDL_CreateWindow("Primeira janela", 100, 100, 320, 240, 0 | SDL_WINDOW_SHOWN);
    if(janela == NULL){
        printf("Não foi possivel criar a janela: %s", SDL_GetError());
        return 1;
    }


    SDL_Renderer* render = SDL_CreateRenderer(janela, -1, SDL_RENDERER_ACCELERATED);
    if(render == NULL){
        printf("Erro ao criar o reder: %s", SDL_GetError());
    }

    SDL_Surface* imagem = SDL_LoadBMP("circulo.bmp");
    if(imagem == NULL){
        printf("Não foi possivel carregar a imagem");
    }

    SDL_Texture* textura = SDL_CreateTextureFromSurface(render, imagem);

    SDL_FreeSurface(imagem);

    SDL_RenderClear(render);
    SDL_RenderCopy(render, textura, NULL, NULL);
    SDL_RenderPresent(render);


    SDL_Delay(5000);

    SDL_DestroyTexture(textura);
    SDL_DestroyRenderer(render);


    SDL_DestroyWindow(janela);

    SDL_Quit();
    return 0;
}


    Para este tutorial foi aproveitado praticamente todo o código do tutorial anterior onde criamos uma janela, por isso essa parte não será explicada novamente.

                                                                          circulo.bmp


    Aqui criamos o reder, onde tudo será desenhado. No primeiro parâmetro passado a função associamos o render a janela, o segundo deixamos em -1 e o terceiro é o tipo de reder, que neste caso é acelerado por hardware.



SDL_Renderer* render = SDL_CreateRenderer(janela, -1, SDL_RENDERER_ACCELERATED);
    if(render == NULL){
        printf("Erro ao criar o reder: %s", SDL_GetError());
    }


     Neste trecho do código é onde carregamos a imagem a ser desenhada para a memória utilizando a estrutura SDL_Surface para guardar estes dados.



SDL_Surface* imagem =  SDL_LoadBMP("circulo.bmp");
    if(imagem == NULL){
        printf("Não foi possível carregar a imagem");
    }


    Depois de carregar a imagem devemos convertê-la para o formato SDL_Texture, este que será usado para desenhar na tela


SDL_Texture* textura = SDL_CreateTextureFromSurface(render, imagem);


    Com a textura já carregada devemos liberar o espaço na memória ocupado pela surface que foi usada para carregar a imagem.

SDL_FreeSurface(imagem);


    A função SDL_RenderClear é usada para limpar a tela preenchendo-a com uma cor específica que pode ser selecionada com a função SDL_SetRenderDrawColor().Por padrão a cor de preenchimento é o preto.

SDL_RenderClear(render);

    Enquanto isso SDL_RenderCopy copia a textura para a render onde será exibida. No primeiro parâmetro passamos o render onde será desenhado a textura, o segundo parâmetro é a textura a ser desenhada e o terceiro e quarto parâmetro se referem a coordenadas da imagem e será explicado no próximo tutorial, como não são especificados a imagem ocupa a tela toda. 

SDL_RenderCopy(render, textura, NULL, NULL);

    A função abaixo faz com que a reder seja exibida.

SDL_RenderPresent(render);

    Para liberar memória, assim como a janela, tanto a textura como o render dever ser finalizados.


SDL_DestroyTexture(textura);
SDL_DestroyRenderer(render);

    Por fim temos a nossa tela.



    Agradeço a visita de todos e qualquer dúvida ou sugestão é só deixar ai nos comentários. Obrigado e até o próximo.

4 comentários:

  1. Excelente material! Completo e bem didático... Muito obrigada! Mas estou ficando preocupada pois não tenho visto postagens novas sobre SDL2....

    ResponderExcluir
    Respostas
    1. Alguns probleminhas aqui, começo a postar novamente até o começo do mês de junho. Pretendo então ir colocando, pelo menos, um novo por semana. Pode ficar despreocupada, não pretendo parar não :D

      Excluir
  2. Se eu estiver com a biblioteca img da sdl instalada e fizer isso
    linhaVerticalCinza= IMG_Load("Imagens/linhaVcinza.png");
    tLinhaVerticalCinza = SDL_CreateTextureFromSurface(render, linhaVerticalCinza);
    Daria certo? Não entendo porque tlinhavertical nao esta recebendo nada

    ResponderExcluir
    Respostas
    1. Boa noite!
      Você tentou checar onde ocorre o erro sé é ao carregar a imagem ou ao criar a textura?

      if (linhaVerticalCinza == NULL) {
      fprintf(stderr, "Erro criando a surface: %s\n", SDL_GetError());
      exit(1);
      }

      e


      if (tLinhaVerticalCinza == NULL) {
      fprintf(stderr, "Erro criando a textura: %s\n", SDL_GetError());
      exit(1);
      }

      Excluir