저번에 이미지를 띄우기 위하여 SDL_image 를 설치하였다. 이제 이미지를 불러와서 출력해보자.
SDL 에는 화면에 이미지를 출력하는 2가지 방법이 있다.
첫번째는 Surface 로 이미지를 출력하는것 두번째는 Texture 로 이미지를 출력하는것이다.
Surface 는 소프트웨어 가속이고, Texture 는 하드웨어 가속에 쓰인다. 자세한 설명은 구글에..
먼저 Surface 를 이용해서 이미지를 출력하는 방법을 알아보자.
간단한 원리는, 이미지를 surface 로 불러오고, window 에 있는 surface 에 이미지 surface 를 붙여넣는 방식이다.
함수를 하나씩 알아보자
사전 준비
지금까지와는 다르게 렌더러를 사용하지 않습니다.
먼저 윈도우에 최종적으로 출력될 Surface 를 아래의 함수로 받아옵니다.
SDL_image 를 사용하기 위한 초기화 작업도 진쟁합니다.
SDL_GetWindowSurface
A new surface will be created with the optimal format for the window
윈도우에 맞는 최적 포맷의 Surface 를 만듭니다. (윈도우의 서피스를 가져온다고 생각)
function
SDL_Surface * SDLCALL SDL_GetWindowSurface(SDL_Window * window);
C
복사
parameters
•
window : 윈도우
return value
•
the surface associated with the window, or NULL on failure
example
windowSurface = SDL_GetWindowSurface(window);
C
복사
IMG_Init
SDL_image 를 초기화합니다.
function
int SDLCALL IMG_Init(int flags);
C
복사
parameters
•
flags : 불러올 이미지 종류
◦
IMG_INIT_JPG
◦
IMG_INIT_PNG
◦
IMG_INIT_TIF
◦
IMG_INIT_WEBP
return value
•
It returns the flags successfully initialized, or 0 on failure.
example
int imgFlags = IMG_INIT_PNG;
if( !( IMG_Init( imgFlags ) & imgFlags ) )
{
printf( "SDL_image could not initialize! SDL_image Error: %s\n", IMG_GetError() );
return (0);
}
C
복사
이미지 불러오기
이제 이미지를 불러오도록 하겠습니다.
IMG_Load
이미지 파일을 불러와 Surface 로 저장합니다.
function
SDL_Surface * SDLCALL IMG_Load(const char *file);
C
복사
parameters
•
file : BMP, GIF, PNG 등
return value
•
생성된 Surface 반환
example
SDL_Surface *surface;
surface = IMG_Load(file);
if(surface == NULL){
printf("%s파일을 읽을 수 없습니다.\n", file);
return NULL;
}
C
복사
SDL_ConvertSurface
window에 Surface 를 출력할떄, 포맷이 다르면 매번 포맷을 변경해서 출력하게 됩니다.
따라서 좀더 최적화를 시키기 위해서 window 에 맞는 포맷으로 미리 바꿔둡니다.
function
SDL_Surface *SDLCALL SDL_ConvertSurface
(SDL_Surface * src, const SDL_PixelFormat * fmt, Uint32 flags);
C
복사
parameters
•
src : 원본 Surface
•
fmt : 바꿀 포맷 (window surface 의 포맷)
•
flags : 이제는 안쓰이고, 그냥 0 넣으면 된다고 한다.
return value
•
the new SDL_Surface structure that is created or NULL if it fails
•
새로운 SDL_Surface 가 생기는것이기 때문에, 기존의 surface 는 free 해줘야한다.
example
optimizedSurface = SDL_ConvertSurface(surface, windowSurface->format, 0);
if (optimizedSurface == NULL)
{
printf("unable to optimize image %s\n", file);
return NULL;
}
SDL_FreeSurface(surface);
C
복사
이미지 출력하기
이미지를 불러왔으니, 이번에는 이미지를 출력시켜보겠다.
SDL_BlitSurface
간단한게 한 Surface 를 다른 Surface 로 복사해서 붙여넣는다고 생각하면 된다.
Blit 이 뭔지에 대한 자세한 설명은 구글링...
function
#define SDL_BlitSurface SDL_UpperBlit
int SDLCALL SDL_UpperBlit
(SDL_Surface * src, const SDL_Rect * srcrect,
SDL_Surface * dst, SDL_Rect * dstrect);
C
복사
parameters
•
src : 복사할 Surface
•
srcrect : 복사할 Surface 에서 복사될 사각형
•
dst : 붙여넣을 Surface
•
dstrect : 붙여넣을 Surface 에서 붙여넣어질 사각형
example
SDL_Rect Rect;
Rect.x = width / 2;
Rect.y = height / 2;
SDL_BlitSurface(image, NULL, windowSurface, &Rect);
C
복사
SDL_UpdateWindowSurface
윈도우의 Surface를 윈도우에 그립니다.
function
int SDLCALL SDL_UpdateWindowSurface(SDL_Window * window);
C
복사
parameters
•
window : 업데이트할 윈도우
return value
•
0 on success or a negative error code on failure
example
SDL_UpdateWindowSurface(window);
C
복사
메모리 해제
마지막으로, 생성한 Surface 에 대해서 메모리를 해제해줍니다. SDL_image 를 종료시킵니다.
SDL_FreeSurface(iamge);
IMG_Quit();
C
복사
최종 코드
최종적으로 아래의 코드를 돌리면 이미지가 뜹니다!
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <stdio.h>
#include <stdbool.h>
SDL_Window *window;
SDL_Surface *windowSurface;
// Window dimensions
static const int width = 800;
static const int height = 600;
static int initAll()
{
if (SDL_Init(SDL_INIT_EVENTS) != 0)
{
fprintf(stderr, "%s\n", (SDL_GetError()));
return (0);
}
window = SDL_CreateWindow("Hello World", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_OPENGL);
if (window == 0)
{
fprintf(stderr, "%s\n", (SDL_GetError()));
return (0);
}
windowSurface = SDL_GetWindowSurface(window);
int imgFlags = IMG_INIT_PNG;
if( !( IMG_Init( imgFlags ) & imgFlags ) )
{
printf( "SDL_image could not initialize! SDL_image Error: %s\n", IMG_GetError() );
return (0);
}
return (1);
}
static void closeAll()
{
SDL_DestroyWindow(window);
IMG_Quit();
SDL_Quit();
}
SDL_Surface *loadImage(const char *file){
SDL_Surface *surface;
SDL_Surface *optimizedSurface;
surface = IMG_Load(file);
if (surface == NULL)
{
printf("fail to read %s\n", file);
return NULL;
}
optimizedSurface = SDL_ConvertSurface(surface, windowSurface->format, 0);
if (optimizedSurface == NULL)
{
printf("unable to optimize image %s\n", file);
return NULL;
}
SDL_FreeSurface(surface);
return optimizedSurface;
}
int main(int argc,char **argv){
initAll();
SDL_Surface *image;
image = loadImage("image.png");
bool quit = false;
SDL_Event event;
while(!quit){
while(SDL_PollEvent(&event)){
switch(event.type){
case SDL_QUIT:
quit = true;
break;
}
}
SDL_Rect Rect;
Rect.x = width / 2;
Rect.y = height / 2;
SDL_BlitSurface(image, NULL, windowSurface, &Rect);
SDL_UpdateWindowSurface(window);
}
SDL_FreeSurface(image);
closeAll();
return 0;
}
C
복사