En anteriores entradas de esta serie hemos visto como crear un makefile y que herramientas usar, hemos visto también como instalar la biblioteca SDL base y como crear una ventana y es el momento de meternos en faena y ver como podemos mostrar un bmp (mapa de bits) dentro de una ventana.
Importante antes de comenzar es crear una serie de directorios y archivos. Aquí la receta:
$ mkdir mostrarimagen $ cd mostrarimagen $ mkdir res bin $ touch makefile mostrarimagen.c
Dentro de makefile meteremos esto:
CC := gcc CFLAGS := -Wall LINKER_FLAGS = `sdl2-config --cflags --libs` test: make clean make build build: $(CC) $(CFLAGS) -o bin/mostrarimagen mostrarimagen.c $(LINKER_FLAGS) run: ./bin/mostrarimagen clean: -rm bin/mostrarimagen
Dentro de mostrarimagen.c meteremos esto:
#include <SDL.h> #include <stdio.h> int main(void) { SDL_Window * ventana; SDL_Surface * imagen; SDL_Renderer * render; SDL_Texture * textura; SDL_Init(SDL_INIT_VIDEO); ventana = SDL_CreateWindow("mostrando una imagen",SDL_WINDOWPOS_UNDEFINED,SDL_WINDOWPOS_UNDEFINED,640,480,SDL_WINDOW_OPENGL); if (ventana == NULL) { printf("No se pudo crear la ventana: %s\n", SDL_GetError()); return 1; } render = SDL_CreateRenderer(ventana, -1, 0); imagen = SDL_LoadBMP("res/imagen.bmp"); textura = SDL_CreateTextureFromSurface(render, imagen); SDL_RenderCopy(render, textura, NULL, NULL); SDL_RenderPresent(render); SDL_Delay(33000); SDL_DestroyTexture(textura); SDL_FreeSurface(imagen); SDL_DestroyRenderer(render); SDL_DestroyWindow(ventana); SDL_Quit(); return 0; }
En el directorio res tenemos que meter esta imagen con el nombre imagen.bmp . Copiaremos el directorio res una vez tiene la imagen dentro del directorio bin así:
$ cp -pRv res/ bin/
Si ejecutamos el programa con «make run» o entrando en el directorio bin y ejecutando ./mostrarimagen veremos esto:
Explicando el código:
Una de las cosas que SDL2 (recordemos que estamos usando SDL2) base (sin necesidad de usar sdl_image) es mostrar un BMP. No obstante para hacer esto hemos de realizar una serie de pasos que voy a intentar explicar sin meter demasiado rollo.
SDL_Window * ventana; SDL_Surface * imagen; SDL_Renderer * render; SDL_Texture * textura;
– Cargaremos la imagen imagen.bmp como surface (superficie).
– Copiaremos la surface como texture (textura).
– Copiaremos la texture como renderer.
Es por eso que primero hemos de declarar esos punteros (ventana, imagen, render, textura).
Nuestra finalidad es que lo que cargamos en memoria a la que accede la CPU (surfaces, RAM) se copie en memoria a la que accede la GPU (textures, video RAM) y lo muestre en la ventana.
Para ello usamos estas funciones:
render = SDL_CreateRenderer(ventana, -1, 0); imagen = SDL_LoadBMP("res/imagen.bmp"); textura = SDL_CreateTextureFromSurface(render, imagen); SDL_RenderCopy(render, textura, NULL, NULL); SDL_RenderPresent(render);
SDL_CreateRenderer Utilizamos esta función para crear un contexto de representación 2D para una ventana llamada ventana y creada anteriormente. Si se llamase toolwindow por ejemplo pues tendríamos que indicar toolwindow, pero en nuestro caso vamos a crearlo para la ventana declarada como ventana. Le metemos -1 para que use la tarjeta gráfica que encuentre y finalmente se puede poner 0 o un flag de los siguientes wiki.libsdl.org/SDL_RendererFlags .
SDL_LoadBMP Utilizamos la función para cargar el mapa de bits imagen.bmp que se encuentra en el directorio res/imagen.bmp al puntero de tipo surface.
SDL_CreateTextureFromSurface Esta función la usaremos para crear una textura desde una surface existente. La textura estará en Vídeo RAM y será memoria para acceder desde la GPU (la tarjeta gráfica). La textura contiene la información de render (el contexto de representación) y el mapa de bits que habíamos cargado como surface).
SDL_RenderCopy Utilizaremos esta función para copiar una parte de la textura al destino de renderizado actual. En realidad vamos a copiar toda la textura al completo aunque podríamos indicar que solo se copiase una parte (mirar wiki.libsdl.org/SDL_Rect ).
SDL_RenderPresent Mostramos o actualizamos la pantalla con la imagen renderizada.
Cuando pasen x segundos que indiquemos la ventana y todo se destruirá. No es lo ideal ni lo normal.
Lo normal será gestionar eventos. Eso en la próxima entrega :).
Saludos cordiales.