2014년 7월 1일 화요일

[일기] SDL에서 png 이미지 출력하기.

1. 확장 라이브러리가 필요하다.

 SDL_image 가 그것이다.

본인은 Windows에서 Visual Studio를 사용하므로 SDL_image를 http://www.libsdl.org/projects/SDL_image/ 에서 다운받고, 필요한 lib를 추가하는 반면, dll 또한 system32 폴더에 위치시켰다.





 포함될 헤더는 SDL_image.h 하나 뿐이다.

이전 튜토리얼 2에서 배운 함수를 변경한다.

 SDL_Texture* MY_LoadTexture(const std::string &file, SDL_Renderer *ren){
SDL_Texture *tex = IMG_LoadTexture(ren, file.c_str());
if (tex == nullptr)
MY_LogSDLError(std::cout, "LoadTexture");
return tex;
}

또한 다른 렌더링 함수를 오버로딩 한다.

void MY_RenderTexture(SDL_Texture *tex, SDL_Renderer *ren, int x, int y, int w, int h){
//우리가 위치시킬 곳을 지정한다. 폭과 높이도 멋대로. 알아서 수축하고 팽창한다.
SDL_Rect dst;
dst.x = x;
dst.y = y;
dst.w = w;
dst.h = h;
SDL_RenderCopy(ren, tex, NULL, &dst);
}

void MY_RenderTexture(SDL_Texture *tex, SDL_Renderer *ren, int x, int y){
int w, h;
SDL_QueryTexture(tex, NULL, NULL, &w, &h);
My_RenderTexture(tex, ren, x, y, w, h);
}


SDL_image를 새로 영입(?)했기 때문에 이를 초기화해야 한다. 본인은 PNG만 출력하면 되었으므로,

IMG_Init을 호출하되, IMG_INIT_PNG만을 플래그로 하여 인자로 전달한다. SDL_image에서는 이미지 로딩 시 자동으로 필요한 이미지를 초기화하는데, 이는 시간적 지연을 발생시키므로 미리 로딩한다. 사용된 함수는 현재 초기화된 이미지 로더의 비트마스크를 리턴한다.

//main

if ( (IMG_Init(IMG_INIT_PNG) & IMG_INIT_PNG) != IMG_INIT_PNG ) {
         MY_LogSDLError(std::cout, "IMG_Init");
         return 1;
}

이제 출력해보자. 아래의 코드는 튜토리얼 2에서와 동일하다. 경로 제외.

const std::string resPath = getResourcePath();
SDL_Texture *background = loadTexture(resPath + "background.png", ren);
SDL_Texture *foreground= loadTexture(resPath + "foreground.png", ren);
//Make sure they both loaded ok
if (background == nullptr || foreground == nullptr)
return 4;

이미지 출처 : http://www.willusher.io/sdl2%20tutorials/2013/08/18/lesson-3-sdl-extension-libraries/


int recordTutorialThree(int argc, char* argv[]){
if(SDL_Init(SDL_INIT_EVERYTHING) != 0){
MY_LogSDLError(std::cout, "SDL_Init");
return 1;
}

SDL_Window *win = SDL_CreateWindow("Tutorial 2", 100, 100,
WIDTH_OF_SCREEN, HEIGHT_OF_SCREEN, SDL_WINDOW_SHOWN);

if(win == nullptr){
MY_LogSDLError(std::cout, "CreateWindow");
return 2;
}
SDL_Renderer *ren = SDL_CreateRenderer(win, -1,
SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if(ren == nullptr) {
MY_LogSDLError(std::cout, "CreateRenderer");
return 3;
}

const std::string resPath = getResourcePath();
SDL_Texture* background = MY_LoadTexture(resPath + "background.png", ren);
SDL_Texture* foreground = MY_LoadTexture(resPath + "imaged.png", ren);


SDL_RenderClear(ren); //지우기

int bW, bH;
SDL_QueryTexture(background, NULL, NULL, &bW, &bH);
MY_RenderTexture(background, ren, 0, 0);
MY_RenderTexture(background, ren, bW, 0);
MY_RenderTexture(background, ren, 0, bH);
MY_RenderTexture(background, ren, bW, bH);

//실제 그린다.
int iW, iH;
SDL_QueryTexture(foreground, NULL, NULL, &iW, &iH);
int x = WIDTH_OF_SCREEN / 2 - iW / 2;
int y = HEIGHT_OF_SCREEN / 2 - iH / 2;
MY_RenderTexture(foreground, ren, x, y);

SDL_RenderPresent(ren); //화면에 출력
SDL_Delay(2000); //2초 대기


if(background == nullptr || foreground == nullptr){
return 4;
}

SDL_DestroyTexture(background);
SDL_DestroyTexture(foreground);
SDL_DestroyRenderer(ren);
SDL_DestroyWindow(win);
SDL_Quit();
 IMG_Quit();

return 0;
}

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

return recordTutorialThree(argc, argv);
}

위는 테스트 코드.

아래는 결과.


댓글 없음:

댓글 쓰기