Search
Duplicate
🍏

SDL 2.0 을 알아보자 (5탄) - Surface 이미지 출력하기

간단소개
팔만코딩경 컨트리뷰터
ContributorNotionAccount
주제 / 분류
C
Graphics
Scrap
태그
9 more properties
저번에 이미지를 띄우기 위하여 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
복사

Reference