[SDL] SDL OpenCV

SDL, raylib 2024. 1. 27. 01:00 |
반응형

SDL에서 OpenCV를 사용해 보자.

 

아래와 같이 비주얼 스튜디오에서 SDL과 OpenCV를 사용할 수 있도록 적절히 세팅한다.

 

 

 

 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include <iostream>
#include "SDL.h"
#include "opencv2/opencv.hpp"
 
int main(int argc, char* argv[]) {
    SDL_Init(SDL_INIT_VIDEO);
    SDL_Window* window = SDL_CreateWindow("SDL Test", SDL_WINDOWPOS_UNDEFINED,
        SDL_WINDOWPOS_UNDEFINED, 640480, SDL_WINDOW_RESIZABLE);
    SDL_Renderer* renderer = SDL_CreateRenderer(window, -10);
 
    //////////////////// cv::Mat to SDL_Texture ////////////////////
    cv::Mat image = cv::imread("image.png", cv::IMREAD_COLOR);
    SDL_Rect destRect = { 00, image.cols, image.rows };
    SDL_Texture* texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_BGR24,
        SDL_TEXTUREACCESS_STREAMING, image.cols, image.rows);
    SDL_UpdateTexture(texture, NULL, (void*)image.data, image.step1());
    // SDL_UpdateTexture() 대신 아래 주석 처리된 코드를 사용할 수도 있다.
    // #include <opencv2/core/types_c.h> 필요.
 
    /*
    IplImage iplImage = cvIplImage(image);
    unsigned char* texture_data = NULL;
    int texture_pitch = 0;
    SDL_LockTexture(texture, 0, (void**)&texture_data, &texture_pitch);
    memcpy(texture_data, (void*)iplImage.imageData,
        iplImage.width * iplImage.height * iplImage.nChannels);
    SDL_UnlockTexture(texture);
    */
    ////////////////////////////////////////////////////////////////
 
    SDL_Event event;
    bool quit = false;
 
    while (!quit) {
        while (SDL_PollEvent(&event)) {
            switch (event.type) {
            case SDL_QUIT:
                quit = true;
                break;
            case SDL_KEYDOWN:
                printf("Key pressed: %s\n", SDL_GetKeyName(event.key.keysym.sym));
                if (event.key.keysym.sym == SDLK_ESCAPE)
                    quit = true;
                break;
            default:
                break;
            }
        }
 
        SDL_SetRenderDrawColor(renderer, 255255255, SDL_ALPHA_OPAQUE);
        SDL_RenderClear(renderer);
        SDL_RenderCopy(renderer, texture, NULL&destRect);
        SDL_RenderPresent(renderer);
    }
 
    SDL_DestroyTexture(texture);
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    SDL_Quit();
 
    return 0;
}
 

 

코드를 작성하고 빌드한다.

 

실행하면 이미지가 출력된다.

 

반응형
Posted by J-sean
:
반응형

SDL에서 ImGui를 이용해 간단한 그래픽 유저 인터페이스를 구현해 보자.

 

비주얼 스튜디오에서 C++ 프로젝트를 만들고 소스파일(Source.cpp)을 추가한다.

SDL을 사용하기 위한 Include, Library 디렉토리 설정 등을 진행하고 ..\imgui-1.90.1\backends 에서 imgui_impl_sdl2.*, imgui_impl_sdlrenderer2.* 파일들을 복사한다. 나머지 파일들은 ..\imgui-1.90.1 에서 복사한다.

 

필터(ImGui)를 추가하고 복사한 파일들을 프로젝트에 추가한다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#include <iostream>
#include "SDL.h"
#include "imgui.h"
#include "imgui_impl_sdl2.h"
#include "imgui_impl_sdlrenderer2.h"
 
int main(int argc, char* argv[]) {
    SDL_Init(SDL_INIT_VIDEO);
    SDL_Window* window = SDL_CreateWindow("SDL Test", SDL_WINDOWPOS_UNDEFINED,
        SDL_WINDOWPOS_UNDEFINED, 640480, SDL_WINDOW_RESIZABLE);
    SDL_Renderer* renderer = SDL_CreateRenderer(window, -10);
 
    // Setup Dear ImGui context
    IMGUI_CHECKVERSION();
    ImGui::CreateContext();
    ImGuiIO& io = ImGui::GetIO();
    io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
    //io.Fonts->AddFontFromFileTTF("newfont.ttf", 20);
    // If no fonts are loaded, dear imgui will use the default font.
 
    // Setup Dear ImGui style    
    ImGui::StyleColorsLight();
    //ImGui::StyleColorsDark();
 
    // Setup Platform/Renderer backends
    ImGui_ImplSDL2_InitForSDLRenderer(window, renderer);
    ImGui_ImplSDLRenderer2_Init(renderer);
 
    // Our state
    bool show_demo_window = true;
    bool show_another_window = false;
    ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
 
    SDL_Event event;
    bool quit = false;
 
    // Poll and handle events (inputs, window resize, etc.)
    // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to
    // use your inputs.
    // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or
    // clear/overwrite your copy of the mouse data.
    // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application,
    // or clear/overwrite your copy of the keyboard data.
    // Generally you may always pass all inputs to dear imgui, and hide them from your application based on
    // those two flags.
    while (!quit) {
        while (SDL_PollEvent(&event)) {
            ImGui_ImplSDL2_ProcessEvent(&event);
            switch (event.type) {
            case SDL_QUIT:
                quit = true;
                break;
            case SDL_KEYDOWN:
                printf("Key pressed: %s\n", SDL_GetKeyName(event.key.keysym.sym));
                if (event.key.keysym.sym == SDLK_ESCAPE)
                    quit = true;
                break;
            default:
                break;
            }
        }
 
        // Start the Dear ImGui frame
        ImGui_ImplSDLRenderer2_NewFrame();
        ImGui_ImplSDL2_NewFrame();
        ImGui::NewFrame();
 
        // Show a simple window that we create ourselves. We use a Begin/End pair to create a named window.
        {
            static float f = 0.0f;
            static int counter = 0;
 
            ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
 
            ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
            ImGui::Checkbox("Demo Window"&show_demo_window); // Edit bools storing our window open/close state
            ImGui::Checkbox("Another Window"&show_another_window);
 
            ImGui::SliderFloat("float"&f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
            ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
 
            if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
                counter++;
            ImGui::SameLine();
            ImGui::Text("counter = %d", counter);
 
            ImGui::Text("Application average %.3f ms/frame (%.1f FPS)"1000.0f / io.Framerate, io.Framerate);
            ImGui::End();
        }
 
        // Show another simple window.
        if (show_another_window)
        {
            ImGui::Begin("Another Window"&show_another_window);
            // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
            ImGui::Text("Hello from another window!");
            if (ImGui::Button("Close Me"))
                show_another_window = false;
            ImGui::End();
        }
 
        // Show only a button at (0, 0).
        {
            ImGui::SetNextWindowPos(ImVec2(00), ImGuiCond_Always);
            ImGui::Begin("No Name"NULL, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDecoration
                | ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoSavedSettings);
            if (ImGui::Button("MyButton", ImVec2(200100))) {
                std::cout << "Clicked" << std::endl;
            }
            ImGui::End();
        }
 
        // Rendering
        ImGui::Render();
        SDL_SetRenderDrawColor(renderer, 255255255, SDL_ALPHA_OPAQUE);
        SDL_RenderClear(renderer);
        ImGui_ImplSDLRenderer2_RenderDrawData(ImGui::GetDrawData());
        SDL_RenderPresent(renderer);
    }
 
    // Cleanup
    ImGui_ImplSDLRenderer2_Shutdown();
    ImGui_ImplSDL2_Shutdown();
    ImGui::DestroyContext();
 
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    SDL_Quit();
 
    return 0;
}
 

 

코드를 입력하고 빌드한다.

 

실행하면 윈도우에 GUI가 출력된다.

 

ImGui의 스타일(테마)은 아래와 같이 개별적으로도 지정할 수 있다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// Setup Dear ImGui style
//ImGui::StyleColorsLight();
//ImGui::StyleColorsDark();
ImGuiStyle& style = ImGui::GetStyle();
 
style.Colors[ImGuiCol_Text] = ImVec4(0.86f, 0.93f, 0.89f, 0.78f);
style.Colors[ImGuiCol_TextDisabled] = ImVec4(0.86f, 0.93f, 0.89f, 0.28f);
style.Colors[ImGuiCol_WindowBg] = ImVec4(0.13f, 0.14f, 0.17f, 1.00f);
style.Colors[ImGuiCol_Border] = ImVec4(0.31f, 0.31f, 1.00f, 0.00f);
style.Colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
style.Colors[ImGuiCol_FrameBg] = ImVec4(0.20f, 0.22f, 0.27f, 1.00f);
style.Colors[ImGuiCol_FrameBgHovered] = ImVec4(0.92f, 0.18f, 0.29f, 0.78f);
style.Colors[ImGuiCol_FrameBgActive] = ImVec4(0.92f, 0.18f, 0.29f, 1.00f);
style.Colors[ImGuiCol_TitleBg] = ImVec4(0.20f, 0.22f, 0.27f, 1.00f);
style.Colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.20f, 0.22f, 0.27f, 0.75f);
style.Colors[ImGuiCol_TitleBgActive] = ImVec4(0.92f, 0.18f, 0.29f, 1.00f);
style.Colors[ImGuiCol_MenuBarBg] = ImVec4(0.20f, 0.22f, 0.27f, 0.47f);
style.Colors[ImGuiCol_ScrollbarBg] = ImVec4(0.20f, 0.22f, 0.27f, 1.00f);
style.Colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.09f, 0.15f, 0.16f, 1.00f);
style.Colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.92f, 0.18f, 0.29f, 0.78f);
style.Colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.92f, 0.18f, 0.29f, 1.00f);
style.Colors[ImGuiCol_CheckMark] = ImVec4(0.71f, 0.22f, 0.27f, 1.00f);
style.Colors[ImGuiCol_SliderGrab] = ImVec4(0.47f, 0.77f, 0.83f, 0.14f);
style.Colors[ImGuiCol_SliderGrabActive] = ImVec4(0.92f, 0.18f, 0.29f, 1.00f);
style.Colors[ImGuiCol_Button] = ImVec4(0.92f, 0.18f, 0.29f, 0.70f);
style.Colors[ImGuiCol_ButtonHovered] = ImVec4(0.92f, 0.18f, 0.29f, 0.86f);
style.Colors[ImGuiCol_ButtonActive] = ImVec4(0.92f, 0.18f, 0.29f, 1.00f);
style.Colors[ImGuiCol_Header] = ImVec4(0.92f, 0.18f, 0.29f, 0.76f);
style.Colors[ImGuiCol_HeaderHovered] = ImVec4(0.92f, 0.18f, 0.29f, 0.86f);
style.Colors[ImGuiCol_HeaderActive] = ImVec4(0.92f, 0.18f, 0.29f, 1.00f);
style.Colors[ImGuiCol_Separator] = ImVec4(0.14f, 0.16f, 0.19f, 1.00f);
style.Colors[ImGuiCol_SeparatorHovered] = ImVec4(0.92f, 0.18f, 0.29f, 0.78f);
style.Colors[ImGuiCol_SeparatorActive] = ImVec4(0.92f, 0.18f, 0.29f, 1.00f);
style.Colors[ImGuiCol_ResizeGrip] = ImVec4(0.47f, 0.77f, 0.83f, 0.04f);
style.Colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.92f, 0.18f, 0.29f, 0.78f);
style.Colors[ImGuiCol_ResizeGripActive] = ImVec4(0.92f, 0.18f, 0.29f, 1.00f);
style.Colors[ImGuiCol_PlotLines] = ImVec4(0.86f, 0.93f, 0.89f, 0.63f);
style.Colors[ImGuiCol_PlotLinesHovered] = ImVec4(0.92f, 0.18f, 0.29f, 1.00f);
style.Colors[ImGuiCol_PlotHistogram] = ImVec4(0.86f, 0.93f, 0.89f, 0.63f);
style.Colors[ImGuiCol_PlotHistogramHovered] = ImVec4(0.92f, 0.18f, 0.29f, 1.00f);
style.Colors[ImGuiCol_TextSelectedBg] = ImVec4(0.92f, 0.18f, 0.29f, 0.43f);
style.Colors[ImGuiCol_PopupBg] = ImVec4(0.20f, 0.22f, 0.27f, 0.9f);
style.Colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.20f, 0.22f, 0.27f, 0.73f);
 

 

 

※ 참고

Dear ImGui는 API Reference가 없다. Python 래퍼 pyimgui 를 참고하자.

pyimgui

 

반응형
Posted by J-sean
:
반응형

SDL 에는 GUI 기능이 없어 다른 라이브러리를 사용해야 한다. 많은 GUI 라이브러리가 있는데 ImGui 를 확인해 보자.

아래 링크에서 ImGui를 다운로드 한다.

Dear ImGui

 

압축을 풀고 examples - imgui_examples.sln 파일을 실행한다.

 

비주얼 스튜디오 버전이 다르면 프로젝트를 업그레이드 한다.

 

sdlrenderer2를 startup 프로젝트로 설정한다.

 

main.cpp 파일을 확인하자.

 

 

SDL 관련 명령에서 에러가 발생한다.

 

Project Property Pages - Additional Include Directories 에 정확한 SDL Include 디렉토리를 지정한다.

 

Project Property Pages - Additional Library Directories 에 정확한 SDL Library 디렉토리를 지정한다.

 

프로젝트를 빌드한다.

 

실행하면 윈도우에 GUI가 출력된다. (SDL2.dll 파일이 없다는 에러가 발생하면 복사해 넣어준다)

 

 

이번엔 내가 직접 만든 프로젝트에서 ImGui 예제를 실행해 보자.

 

ImGui 라이브러리 디렉토리는 위 그림과 같이 구성 되어 있다.

 

비주얼 스튜디오 프로젝트를 만들고 소스 파일 하나만 추가한다.

 

SDL2.dll 파일을 찾을 수 있도록 환경을 설정한다.

 

SDL과 ImGui에서 사용하는 Include 디렉토리를 설정한다.

 

 

SDL에서 사용하는 Library 디렉토리를 설정한다.

 

SDL에서 사용하는 라이브러리 파일을 설정한다.

 

ImGui, ImGui-Backend 필터를 만들고 ImGui SDL 예제에서 사용하는 파일을 추가한다.

 

처음에 만들어둔 소스 파일에 예제 소스파일(..\imgui-1.90.1\examples\example_sdl2_sdlrenderer2\main.cpp) 내용을 복사하고 빌드한다.

 

 

실행하면 운도우에 GUI가 출력된다.

 

※ 참고

Getting Started

 

반응형
Posted by J-sean
:
반응형

SDL 기본 라이브러리는 WAV 형식의 오디오만 처리할 수 있다. mp3, ogg 등의 형식을 처리하기 위해서는 SDL_mixer 라이브러리가 필요하다.

 

우선 SDL 기본 라이브러리로 WAV 사운드를 출력해 보자.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <iostream>
#include "SDL.h"
 
#pragma comment(lib, "sdl2.lib")
#pragma comment(lib, "sdl2main.lib")
 
int main(int argc, char* argv[]) {
    SDL_Init(SDL_INIT_AUDIO);
 
    SDL_AudioSpec wav_spec;
    Uint8* wav_buffer;
    Uint32 wav_length;
 
    if (SDL_LoadWAV("sound.wav"&wav_spec, &wav_buffer, &wav_length) == NULL) {
        // Use this function to load a WAVE from a file.
        printf("SDL_LoadWAV Error: %s\n", SDL_GetError());
        return -1;
    }
 
    int bitDepth = SDL_AUDIO_BITSIZE(wav_spec.format);
    int bytesPerSecond = (bitDepth * wav_spec.channels * wav_spec.freq) / 8;
    float durationSec = (float)wav_length / bytesPerSecond;
    printf("Duration: %f\n", durationSec);
    // wav 파일 재생 시간 구하기.
 
    SDL_AudioDeviceID dev = SDL_OpenAudioDevice(NULL0&wav_spec, NULL0);
    // Open a specific audio device.
    if (dev == NULL) {
        printf("SDL_AudioDeviceID Error: %s\n", SDL_GetError());
        return -1;
    }
 
    if (SDL_QueueAudio(dev, wav_buffer, wav_length) != 0) {
        // Queue more audio on non-callback devices.
        printf("SDL_QueueAudio Error: %s\n", SDL_GetError());
        return -1;
    }
 
    SDL_PauseAudioDevice(dev, 0);
    // Use this function to pause and unpause audio playback on a specified device.
    // dev: a device opened by SDL_OpenAudioDevice()
    // pause_on: non-zero to pause, 0 to unpause
    SDL_Delay(durationSec * 1000);
    // Wait a specified number of milliseconds before returning.
 
    SDL_FreeWAV(wav_buffer);
    // Free data previously allocated with SDL_LoadWAV() or SDL_LoadWAV_RW().
    SDL_CloseAudioDevice(dev);
    //Use this function to shut down audio processing and close the audio device.
    SDL_Quit();
 
    return 0;
}
 

 

코드를 작성하고 빌드한다.

 

실행하면 재생 시간이 표시되고 사운드가 출력된다.

 

※ 참고

SDL_AudioFormat

 

이번엔 SDL_mixer를 이용해 mp3, ogg 등의 사운드를 출력해 보자. 아래 링크에서 SDL_mixer를 다운받고 적당히 설치한다.

SDL Libraries

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <iostream>
#include "SDL.h"
#include "SDL_mixer.h"
 
#pragma comment(lib, "sdl2.lib")
#pragma comment(lib, "sdl2main.lib")
#pragma comment(lib, "sdl2_mixer.lib")
 
int main(int argc, char* argv[]) {
    SDL_Init(SDL_INIT_AUDIO);
 
    if (Mix_OpenAudio(48000, MIX_DEFAULT_FORMAT, 22048!= 0) {
        // Open the default audio device for playback.
        printf("Mix_OpenAudio Error: %s\n", Mix_GetError());
        return -1;
    }
 
    Mix_Music* music = Mix_LoadMUS("sound.mp3");
    // Load a supported audio format into a music object.
    if (music == NULL) {
        printf("Mix_LoadMUS Error: %s\n", Mix_GetError());
        return -1;
    }
    printf("Duration: %f\n", Mix_MusicDuration(music));
    // Get a music object's duration, in seconds.
 
    Mix_PlayMusic(music, 0);
    // Play a new music object. (0 means "play once and stop")
    SDL_Delay(int(Mix_MusicDuration(music) * 1000));
 
    Mix_FreeMusic(music);
    // Free a music object. If this music is currently playing,
    // it will be stopped.
    Mix_CloseAudio();
    // Close the mixer, halting all playing audio.
 
    SDL_Quit();
 
    return 0;
}
 

 

코드를 작성하고 빌드한다.

 

실행하면 재생시간이 표시되고 사운드가 출력된다.

 

※ 참고

SDL_mixer API

 

반응형
Posted by J-sean
:
반응형

로드한 이미지에 컬러키를 설정하고 투명하게 처리해 보자.

 

player.bmp

파란 배경의 BMP 파일을 준비한다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <iostream>
#include "SDL.h"
 
#pragma comment(lib, "sdl2.lib")
#pragma comment(lib, "sdl2main.lib")
 
int main(int argc, char* argv[]) {
    SDL_Init(SDL_INIT_VIDEO);
    SDL_Window* window = SDL_CreateWindow("SDL Test", SDL_WINDOWPOS_UNDEFINED,
        SDL_WINDOWPOS_UNDEFINED, 640480, SDL_WINDOW_RESIZABLE);
    SDL_Renderer* renderer = SDL_CreateRenderer(window, -10);
 
    SDL_Surface* bmpSurface = SDL_LoadBMP("player.bmp");
    SDL_SetColorKey(bmpSurface, SDL_TRUE, SDL_MapRGB(bmpSurface->format, 000xFF));
    // Set the color key (transparent pixel) in a surface.
    // The color key defines a pixel value that will be treated as transparent in a blit.
    // For example, one can use this to specify that cyan pixels should be considered
    // transparent, and therefore not rendered.
    SDL_Rect destRect = { 00, bmpSurface->w, bmpSurface->h };
    SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, bmpSurface);
 
    SDL_Event event;
    bool quit = false;
 
    while (!quit) {
        while (SDL_PollEvent(&event)) {
            switch (event.type) {
            case SDL_QUIT:
                quit = true;
                break;
            case SDL_KEYDOWN:
                printf("Key pressed: %s\n", SDL_GetKeyName(event.key.keysym.sym));
                if (event.key.keysym.sym == SDLK_ESCAPE)
                    quit = true;
                break;
            default:
                break;
            }
        }
 
        SDL_RenderCopy(renderer, texture, NULL&destRect);
        SDL_RenderPresent(renderer);
    }
 
    SDL_FreeSurface(bmpSurface);
    SDL_DestroyTexture(texture);
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    SDL_Quit();
 
    return 0;
}
 

 

파란색(0, 0, 255)을 컬러키로 설정하는 코드를 작성하고 빌드한다.

 

파란색이 투명하게 처리되어 표시된다.

 

컬러키 설정 부분을 주석처리하고 빌드해 보자.

 

//SDL_SetColorKey(bmpSurface, SDL_TRUE, SDL_MapRGB(bmpSurface->format, 0, 0, 0xFF));

 

파란색이 그대로 표시된다.

 

반응형
Posted by J-sean
:
반응형

SDL 기본 라이브러리는 BMP 형식의 이미지만 처리할 수 있다. JPG나 PNG 형식을 처리하기 위해서는 SDL_image 라이브러리가 필요하다.

 

우선 SDL 기본 라이브러리로 BMP 이미지를 렌더링 해 보자.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include <iostream>
#include "SDL.h"
 
#pragma comment(lib, "sdl2.lib")
#pragma comment(lib, "sdl2main.lib")
 
int main(int argc, char* argv[]) {
    if (SDL_Init(SDL_INIT_VIDEO) < 0) {
        printf("SDL Initialization Fail: %s\n", SDL_GetError());
        return -1;
    }
 
    SDL_Window* window = SDL_CreateWindow("SDL Test", SDL_WINDOWPOS_UNDEFINED,
        SDL_WINDOWPOS_UNDEFINED, 640480, SDL_WINDOW_RESIZABLE);
 
    if (!window) {
        printf("SDL_CreateWindow Error: %s\n", SDL_GetError());
        SDL_Quit();
        return -1;
    }
 
    SDL_Renderer* renderer = SDL_CreateRenderer(window, -10);
 
    SDL_Surface* bmpSurface = SDL_LoadBMP("image.bmp");
    // Load a BMP image from a file path.
    if (bmpSurface == NULL) {
        SDL_DestroyRenderer(renderer);
        SDL_DestroyWindow(window);
        printf("SDL_LoadBMP Error: %s\n", SDL_GetError());
        SDL_Quit();
        return -1;
    }
    SDL_Rect destRect = { 00, bmpSurface->w, bmpSurface->h };
 
    SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, bmpSurface);
    // Create a texture from an existing surface.
    if (texture == NULL) {
        SDL_FreeSurface(bmpSurface);
        // Free an RGB surface.
        SDL_DestroyRenderer(renderer);
        SDL_DestroyWindow(window);
        printf("SDL_CreateTextureFromSurface Error: %s\n", SDL_GetError());
        SDL_Quit();
        return -1;
    }
    SDL_FreeSurface(bmpSurface);
 
    SDL_Event event;
    bool quit = false;
 
    while (!quit) {
        while (SDL_PollEvent(&event)) {
            switch (event.type) {
            case SDL_QUIT:
                quit = true;
                break;
            case SDL_KEYDOWN:
                printf("Key pressed: %s\n", SDL_GetKeyName(event.key.keysym.sym));
                if (event.key.keysym.sym == SDLK_ESCAPE)
                    quit = true;
                break;
            default:
                break;
            }
        }
 
        SDL_SetRenderDrawColor(renderer, 255255255, SDL_ALPHA_OPAQUE);
        SDL_RenderClear(renderer);
        SDL_RenderCopy(renderer, texture, NULL&destRect);
        // Copy a portion of the texture to the current rendering target.
        SDL_RenderPresent(renderer);
    }
 
    SDL_DestroyTexture(texture);
    // Destroy the specified texture.
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    SDL_Quit();
 
    return 0;
}
 

 

코드를 작성하고 빌드한다.

 

실행하면 윈도우에 이미지가 렌더링 된다.

 

만약 그래픽 카드의 지원을 받을 수 없는 Embedded System 등에서 소프트웨어 방식의 렌더링만 사용할 수 있다면 Texture, Renderer 를 사용하지 않고 Window Surface, BMP Surface 를 사용해 직접 화면에 이미지를 출력할 수 있다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include <iostream>
#include "SDL.h"
 
#pragma comment(lib, "sdl2.lib")
#pragma comment(lib, "sdl2main.lib")
 
int main(int argc, char* argv[]) {
    if (SDL_Init(SDL_INIT_VIDEO) < 0) {
        printf("SDL Initialization Fail: %s\n", SDL_GetError());
        return -1;
    }
 
    SDL_Window* window = SDL_CreateWindow("SDL Test", SDL_WINDOWPOS_UNDEFINED,
        SDL_WINDOWPOS_UNDEFINED, 640480, SDL_WINDOW_RESIZABLE);
 
    if (!window) {
        printf("SDL_CreateWindow Error: %s\n", SDL_GetError());
        SDL_Quit();
        return -1;
    }
 
    SDL_Surface* windowSurface = SDL_GetWindowSurface(window);
    // Get the SDL surface associated with the window.
    // A new surface will be created with the optimal format for the window,
    // if necessary. This surface will be freed when the window is destroyed.
    // Do not free this surface.
    // This surface will be invalidated if the window is resized. After resizing
    // a window this function must be called again to return a valid surface.
    // You may not combine this with 3D or the rendering API on this window.
 
    SDL_Surface* bmpSurface = SDL_LoadBMP("image.bmp");
    if (bmpSurface == NULL) {
        SDL_DestroyWindow(window);
        printf("SDL_LoadBMP Error: %s\n", SDL_GetError());
        SDL_Quit();
        return -1;
    }
 
    SDL_Event event;
    bool quit = false;
 
    while (!quit) {
        while (SDL_PollEvent(&event)) {
            switch (event.type) {
            case SDL_QUIT:
                quit = true;
                break;
            case SDL_KEYDOWN:
                printf("Key pressed: %s\n", SDL_GetKeyName(event.key.keysym.sym));
                if (event.key.keysym.sym == SDLK_ESCAPE)
                    quit = true;
                break;
            default:
                break;
            }
        }
 
        SDL_BlitSurface(bmpSurface, NULL, windowSurface, NULL);
        // Use this function to perform a fast surface copy to a destination surface.
        SDL_UpdateWindowSurface(window);
        // Copy the window surface to the screen. This is the function you use to
        // reflect any changes to the surface on the screen.
    }
 
    SDL_FreeSurface(bmpSurface);
    SDL_DestroyWindow(window);
    SDL_Quit();
 
    return 0;
}
 

 

코드를 작성하고 빌드한다.

 

윈도우에 이미지가 출력된다.

 

 

 

이번엔 SDL_image를 이용해 JPG, PNG 등의 이미지를 출력해 보자. 아래 링크에서 SDL_image를 다운받고 적당히 설치한다.

SDL Libraries

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include <iostream>
#include "SDL.h"
#include "SDL_image.h"
 
#pragma comment(lib, "sdl2.lib")
#pragma comment(lib, "sdl2main.lib")
#pragma comment(lib, "sdl2_image.lib")
 
int main(int argc, char* argv[]) {
    SDL_Init(SDL_INIT_VIDEO);
    SDL_Window* window = SDL_CreateWindow("SDL Test", SDL_WINDOWPOS_UNDEFINED,
        SDL_WINDOWPOS_UNDEFINED, 640480, SDL_WINDOW_RESIZABLE);
    SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
    // SDL_RENDERER_SOFTWARE: the renderer is a software fallback
    // SDL_RENDERER_ACCELERATED : the renderer uses hardware acceleration
    // SDL_RENDERER_PRESENTVSYNC : present is synchronized with the refresh rate
    // SDL_RENDERER_TARGETTEXTURE : the renderer supports rendering to texture
    // Note that providing no flags gives priority to available SDL_RENDERER_ACCELERATED
    // renderers.
 
    IMG_Init(IMG_INIT_JPG | IMG_INIT_PNG);
    // Initialize SDL_image.
 
    SDL_Surface* imageSurface = IMG_Load("image.png");
    // Load an image from a filesystem path into a software surface.
    SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, imageSurface);
    SDL_Rect destRect = { 00, imageSurface->w, imageSurface->h };
 
    SDL_Event event;
    bool quit = false;
 
    while (!quit) {
        while (SDL_PollEvent(&event)) {
            switch (event.type) {
            case SDL_QUIT:
                quit = true;
                break;
            case SDL_KEYDOWN:
                printf("Key pressed: %s\n", SDL_GetKeyName(event.key.keysym.sym));
                if (event.key.keysym.sym == SDLK_ESCAPE)
                    quit = true;
                break;
            default:
                break;
            }
        }
 
        //SDL_SetRenderDrawColor(renderer, 255, 255, 255, SDL_ALPHA_OPAQUE);
        //SDL_RenderClear(renderer);
        SDL_RenderCopy(renderer, texture, NULL&destRect);
        SDL_RenderPresent(renderer);
    }
 
    SDL_DestroyTexture(texture);
    SDL_FreeSurface(imageSurface);
    IMG_Quit();
    // Deinitialize SDL_image.
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    SDL_Quit();
 
    return 0;
}
 

 

코드를 입력하고 빌드한다.

 

실행하면 윈도우에 이미지가 렌더링 된다.

 

주석처리된 배경 처리 부분을 아래와 같이 해제하고 알파 채널이 있는 PNG 파일을 렌더링 해 보자.

 

SDL_SetRenderDrawColor(renderer, 0, 0, 255, SDL_ALPHA_OPAQUE);
SDL_RenderClear(renderer);

 

player.png
0.00MB

 

 

 

특별한 처리 없이도 알파 채널이 보존되어 투명한 부분이 잘 표현된다.

 

※ 참고

SDL_image API

 

반응형
Posted by J-sean
:
반응형

아래 링크에서 SDL_ttf를 다운받아 설치하고 텍스트를 출력해 보자.

SDL_Libraries

 

SDL_ttf의 include, lib 디렉토리 파일들을 SDL 라이브러리에 적절히 복사한다.

 

sdl2_ttf.lib를 추가한다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#include <iostream>
#include "SDL.h"
#include "SDL_ttf.h"
 
int main(int argc, char* argv[]) {
    if (SDL_Init(SDL_INIT_VIDEO) < 0) {
        printf("SDL Initialization Fail: %s\n", SDL_GetError());
        return -1;
    }
 
    SDL_Window* window = SDL_CreateWindow("Hello World", SDL_WINDOWPOS_UNDEFINED,
        SDL_WINDOWPOS_UNDEFINED, 640480, SDL_WINDOW_RESIZABLE);
 
    if (!window) {
        printf("SDL_CreateWindow Error: %s\n", SDL_GetError());
        SDL_Quit();
        return -1;
    }
 
    SDL_Renderer* renderer = SDL_CreateRenderer(window, -10);
 
    if (TTF_Init() < 0) {
        // Initialize SDL_ttf.
        printf("SDL TTF Initialization Failed: %s\n", TTF_GetError());
        return -1;
    }
 
    TTF_Font* font = TTF_OpenFont("C:\\Windows\\Fonts\\arial.ttf"30);
    // Create a font from a file, using a specified point size.
    if (font == NULL) {
        printf("Could not open font! (%s)\n", TTF_GetError());
        return -1;
    }
    SDL_Color textColor = { 25500 };
    SDL_Surface* textSurface = TTF_RenderText_Blended(font, "Hello World!", textColor);
    // Render Latin1 text at high quality to a new ARGB surface.
    SDL_Texture* textTexture = SDL_CreateTextureFromSurface(renderer, textSurface);
    // Create a texture from an existing surface.
    SDL_FreeSurface(textSurface);
    // Free an RGB surface.
    SDL_Rect destRect = { 1010, textSurface->w, textSurface->h };
    TTF_CloseFont(font);
    // Dispose of a previously-created font.
 
    SDL_Event event;
    bool quit = false;
 
    while (!quit) {
        while (SDL_PollEvent(&event)) {
            switch (event.type) {
            case SDL_QUIT:
                quit = true;
                break;
            case SDL_KEYDOWN:
                printf("Key pressed: %s\n", SDL_GetKeyName(event.key.keysym.sym));
                if (event.key.keysym.sym == SDLK_ESCAPE)
                    quit = true;
                break;
            default:
                break;
            }
        }
 
        SDL_SetRenderDrawColor(renderer, 255255255, SDL_ALPHA_OPAQUE);
        SDL_RenderClear(renderer);
        SDL_RenderCopy(renderer, textTexture, NULL, &destRect);
        // Copy a portion of the texture to the current rendering target.
        SDL_RenderPresent(renderer);
    }
 
    TTF_Quit();
    // Deinitialize SDL_ttf.
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    SDL_Quit();
 
    return 0;
}
 

 

소스를 입력하고 빌드한다.

 

실행하면 윈도우에 텍스트가 렌더링 된다.

※ 참고

SDL_ttf API

 

반응형
Posted by J-sean
:
반응형

아래 링크에서 SDL을 다운로드하고 C++을 이용해 사용할 수 있도록 설정해 보자.

Simple DirectMedia Layer

 

헤더 파일이 있는 Include 디렉토리를 설정한다.

 

라이브러리 파일이 있는 Library 디렉토리를 설정한다.

 

사용할 라이브러리 파일을 설정한다.

 

DLL 파일이 있는 디렉토리를 지정한다.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include <iostream>
#include "SDL.h"
 
int main(int argc, char* argv[]) {
    if (SDL_Init(SDL_INIT_VIDEO) < 0) {
        // Initialize the SDL library.
        printf("SDL Initialization Fail: %s\n", SDL_GetError());
        // Retrieve a message about the last error that occurred on the current thread.
        return -1;
    }
 
    SDL_Window* window = SDL_CreateWindow("Hello World", SDL_WINDOWPOS_UNDEFINED,
        SDL_WINDOWPOS_UNDEFINED, 640480, SDL_WINDOW_RESIZABLE);
    // Create a window with the specified position, dimensions, and flags.
 
    if (!window) {
        printf("SDL_CreateWindow Error: %s\n", SDL_GetError());
        SDL_Quit();
        // Clean up all initialized subsystems.
        return -1;
    }
 
    SDL_Renderer* renderer = SDL_CreateRenderer(window, -10);
    // Create a 2D rendering context for a window.
 
    SDL_Event event;
    bool quit = false;
 
    while (!quit) {
        while (SDL_PollEvent(&event)) {
            // Poll for currently pending events.
            switch (event.type) {
            case SDL_QUIT:
                quit = true;
                break;
            case SDL_KEYDOWN:
                printf("Key pressed: %s\n", SDL_GetKeyName(event.key.keysym.sym));
                if (event.key.keysym.sym == SDLK_ESCAPE)
                    quit = true;
                break;
            default:
                break;
            }
        }
 
        SDL_SetRenderDrawColor(renderer, 255255255, SDL_ALPHA_OPAQUE);
        // Set the color used for drawing operations (Rect, Line and Clear).
        SDL_RenderClear(renderer);
        // Clear the current rendering target with the drawing color.
        SDL_RenderPresent(renderer);
        // Update the screen with any rendering performed since the previous call.
    }
 
    SDL_DestroyRenderer(renderer);
    // Destroy the rendering context for a window and free associated textures.
    SDL_DestroyWindow(window);
    // Destroy a window.
    SDL_Quit();
    // Clean up all initialized subsystems.
 
    return 0;
}
 

 

코드를 입력하고 빌드한다.

 

실행하면 윈도우가 나타난다.

 

콘솔창에는 키입력이 표시된다.

※ 참고

2025.03.30 - [SDL, raylib] - [SDL3] Simple DirectMedia Layer 3 Setup and Getting Started - SDL3 설정 및 초기화

 

반응형
Posted by J-sean
: