C++库——使用SDL2显示一张bmp图片

本文详细介绍如何使用SDL库创建窗口、渲染器,加载并显示图片。从初始化SDL到创建窗口、渲染图片直至清理资源,每一步都有详尽的代码示例。
添加头SDL文件
初始化SDL
创建SDL视窗
创建渲染
创建图片纹理
加载BMP图片
复制到渲染器
显示
循环等待
清理数据
退出SDL

添加SDL头文件

使用sdl库前,需要导入SDL库,cmake构建方法的配置,可以参考如下文章:
cmake:cmake配置SDL库,添加完SDL库后,开始编写代码。

#include <SDL2/SDL.h> //引入sdl的头文件

初始化SDL

使用SDL_Init初始化sdl组件。

//! 函数原型
int SDL_Init(Uint32 flags);

flags参数:定义,宏定义里包括SDL的组件内容,定时器、音频、视频,控制杆,触屏,游戏控制器,事件,传感器和所有的组件。

#define SDL_INIT_TIMER          0x00000001u  /**定时器 */
#define SDL_INIT_AUDIO          0x00000010u  /**音频 */
#define SDL_INIT_VIDEO          0x00000020u  /**< SDL_INIT_VIDEO implies(包含) SDL_INIT_EVENTS 视频包含事件 */
#define SDL_INIT_JOYSTICK       0x00000200u  /**< SDL_INIT_JOYSTICK implies SDL_INIT_EVENTS 控制杆包含事件*/
#define SDL_INIT_HAPTIC         0x00001000u  /*触屏 */
#define SDL_INIT_GAMECONTROLLER 0x00002000u  /**< SDL_INIT_GAMECONTROLLER implies SDL_INIT_JOYSTICK 游戏控制器包含控制杆*/
#define SDL_INIT_EVENTS         0x00004000u  /*事件 */
#define SDL_INIT_SENSOR         0x00008000u  /*传感器 */
#define SDL_INIT_NOPARACHUTE    0x00100000u  /**< compatibility(兼容性); this flag is ignored. */
#define SDL_INIT_EVERYTHING ( \
                SDL_INIT_TIMER | SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_EVENTS | \
                SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMECONTROLLER | SDL_INIT_SENSOR \
            ) /*所有组件全部初始化 */

返回值int:如果返回值为0,证明sdl初始化成功,否则失败,可以使用SDL_GetError()获取失败信息。

if (SDL_Init(SDL_INIT_EVERYTHING)) {
       SDL_Log("Can not init sdl, %s", SDL_GetError());
       return 1;
   }

创建窗口

使用SDL创建窗口

//!函数原型
SDL_Window * SDLCALL SDL_CreateWindow(const char *title,int x, int y, int w,int h, Uint32 flags);

参数title:设置SDL_Window的标题。
参数(x,y):窗口的位置,也可以使用SDL_WINDOWPOS_CENTERED(中心)或者SDL_WINDOWPOS_UNDEFINE(未定义)设置串口的位置。
参数(w,h):窗口的宽和高。
参数flags:创建窗口的形式,包括全屏,使用OPENGL,正常显示,隐藏,无边框,尺寸可调节,最小化,最大化,鼠标被窗口抓取等形式。

typedef enum
{
    SDL_WINDOW_FULLSCREEN = 0x00000001,         /**< fullscreen window */
    SDL_WINDOW_OPENGL = 0x00000002,             /**< window usable with OpenGL context */
    SDL_WINDOW_SHOWN = 0x00000004,              /**< window is visible */
    SDL_WINDOW_HIDDEN = 0x00000008,             /**< window is not visible */
    SDL_WINDOW_BORDERLESS = 0x00000010,         /**< no window decoration */
    SDL_WINDOW_RESIZABLE = 0x00000020,          /**< window can be resized */
    SDL_WINDOW_MINIMIZED = 0x00000040,          /**< window is minimized */
    SDL_WINDOW_MAXIMIZED = 0x00000080,          /**< window is maximized */
    SDL_WINDOW_MOUSE_GRABBED = 0x00000100,      /**< window has grabbed mouse input 鼠标被窗口抓取,鼠标只能在窗口内移动*/
    SDL_WINDOW_INPUT_FOCUS = 0x00000200,        /**< window has input focus */
    SDL_WINDOW_MOUSE_FOCUS = 0x00000400,        /**< window has mouse focus */
    SDL_WINDOW_FULLSCREEN_DESKTOP = ( SDL_WINDOW_FULLSCREEN | 0x00001000 ),
    SDL_WINDOW_FOREIGN = 0x00000800,            /**< window not created by SDL */
    SDL_WINDOW_ALLOW_HIGHDPI = 0x00002000,      /**< window should be created in high-DPI mode if supported.
                                                     On macOS NSHighResolutionCapable must be set true in the
                                                     application's Info.plist for this to have any effect. */
    SDL_WINDOW_MOUSE_CAPTURE    = 0x00004000,   /**< window has mouse captured (unrelated to MOUSE_GRABBED) */
    SDL_WINDOW_ALWAYS_ON_TOP    = 0x00008000,   /**< window should always be above others */
    SDL_WINDOW_SKIP_TASKBAR     = 0x00010000,   /**< window should not be added to the taskbar */
    SDL_WINDOW_UTILITY          = 0x00020000,   /**< window should be treated as a utility window */
    SDL_WINDOW_TOOLTIP          = 0x00040000,   /**< window should be treated as a tooltip */
    SDL_WINDOW_POPUP_MENU       = 0x00080000,   /**< window should be treated as a popup menu */
    SDL_WINDOW_KEYBOARD_GRABBED = 0x00100000,   /**< window has grabbed keyboard input */
    SDL_WINDOW_VULKAN           = 0x10000000,   /**< window usable for Vulkan surface */
    SDL_WINDOW_METAL            = 0x20000000,   /**< window usable for Metal view */
    SDL_WINDOW_INPUT_GRABBED = SDL_WINDOW_MOUSE_GRABBED /**< equivalent to SDL_WINDOW_MOUSE_GRABBED for compatibility */
} SDL_WindowFlags;

返回值:如果返回指针为NULL,说明创建window失败。

SDL_Window *pWindow = SDL_CreateWindow(
        "Hello World",
        SDL_WINDOWPOS_CENTERED,
        SDL_WINDOWPOS_CENTERED,
        WIDTH, HEIGHT,
        SDL_WINDOW_RESIZABLE
);
if (pWindow == NULL) {
    SDL_Log("Can not create window, %s", SDL_GetError());
    return 1;
}

创建渲染器

函数原型

SDL_Renderer *SDL_CreateRenderer(SDL_Window *window,int index, Uint32 flags);

参数window:渲染的SDL窗口
参数index:显示render的驱动,如果为-1,则为默认的驱动。详见
参数flags:

typedef enum
{
    SDL_RENDERER_SOFTWARE = 0x00000001,         /**< The renderer is a software fallback渲染器是软件回退 */
    SDL_RENDERER_ACCELERATED = 0x00000002,      /**< The renderer uses hardware
                                                     acceleration 渲染器使用硬件加速 */
    SDL_RENDERER_PRESENTVSYNC = 0x00000004,     /**< Present is synchronized
                                                     with the refresh rate 存在与刷新率同步 */
    SDL_RENDERER_TARGETTEXTURE = 0x00000008     /**< The renderer supports
                                                     rendering to texture 渲染器支持渲染到纹理 */
} SDL_RendererFlags;

返回值:如果返回指针为NULL,说明创建渲染器失败。

SDL_Renderer *pRenderer = SDL_CreateRenderer(pWindow, -1, SDL_RENDERER_ACCELERATED);
if(pRenderer == NULL)
{
    SDL_Log("Can not create pRenderer, %s", SDL_GetError());
    return 1;
}

加载BMP图片

宏定义原型

SDL_Surface * 
#define SDL_LoadBMP(file)

参数file:bmp文件的路径
返回值:如果SDL_Surface指针为空,说明创建失败。

SDL_Surface *pSurface = SDL_LoadBMP("hello.bmp");
if(pSurface == NULL)
{
    SDL_Log("Can not create pSurface, %s", SDL_GetError());
    return 1;
}

创建纹理

SDL_Texture * SDL_CreateTextureFromSurface(SDL_Renderer * renderer, SDL_Surface * surface);

参数renderer:渲染器
参数surface:表面

SDL_Texture *pTexture = SDL_CreateTextureFromSurface(pRenderer, pSurface);
if(pTexture == NULL)
{
    SDL_Log("Can not create pTexture, %s", SDL_GetError());
    return 1;
}

纹理复制到渲染器

SDL_RenderCopy(SDL_Renderer * renderer,SDL_Texture * texture,const SDL_Rect * srcrect,const SDL_Rect * dstrect);

参数:renderer:渲染器
参数texture:纹理
参数srcrect:裁剪图片尺寸,如果为NULL,显示原始尺寸
参数strect:定义渲染的矩形框,如果为NULL,显示渲染层为原始尺寸

if(0!=SDL_RenderCopy(pRenderer,pTexture,NULL,NULL))
{
    SDL_Log("Can not create RenderCopy, %s", SDL_GetError());
    return 1;
}

显示

函数原型

void SDL_RenderPresent(SDL_Renderer * renderer);

使用

SDL_RenderPresent(pRenderer);

事件等待

    SDL_Event event;
    bool isRun = true;
    while(isRun)
    {
        SDL_WaitEvent(&event);
        switch (event.type) {
            case SDL_QUIT:{
                isRun = false;
            }break;
        }
    }

清理

    SDL_DestroyTexture(pTexture);//清理纹理
    SDL_FreeSurface(pSurface);//清理表面
    SDL_RenderClear(pRenderer);//清理渲染器
    SDL_DestroyWindow(pWindow);//清理窗口
    SDL_Quit();//退出SDL

源码

#include <stdio.h>
#include <SDL2/SDL.h>

#undef main

#define WIDTH 1200
#define HEIGHT 500

int main(int argc, char *argv[]) {
    if (SDL_Init(SDL_INIT_EVERYTHING)) {
        SDL_Log("Can not init sdl, %s", SDL_GetError());
        return 1;
    }

    SDL_Window *pWindow = SDL_CreateWindow(
            "Hello World",
            SDL_WINDOWPOS_CENTERED,
            SDL_WINDOWPOS_CENTERED,
            WIDTH, HEIGHT,
            SDL_WINDOW_RESIZABLE
    );
    if (pWindow == NULL) {
        SDL_Log("Can not create window, %s", SDL_GetError());
        return 1;
    }



    printf("%d",SDL_GetNumRenderDrivers());

    SDL_Renderer *pRenderer = SDL_CreateRenderer(pWindow, -1, SDL_RENDERER_ACCELERATED);
    if(pRenderer == NULL)
    {
        SDL_Log("Can not create pRenderer, %s", SDL_GetError());
        return 1;
    }
    SDL_Surface *pSurface = SDL_LoadBMP("hello.bmp");
    if(pSurface == NULL)
    {
        SDL_Log("Can not create pSurface, %s", SDL_GetError());
        return 1;
    }
    SDL_Texture *pTexture = SDL_CreateTextureFromSurface(pRenderer, pSurface);
    if(pTexture == NULL)
    {
        SDL_Log("Can not create pTexture, %s", SDL_GetError());
        return 1;
    }
    SDL_Rect rect{1,1,400,300};
    if(0!=SDL_RenderCopy(pRenderer,pTexture,&rect,&rect))
    {
        SDL_Log("Can not create RenderCopy, %s", SDL_GetError());
        return 1;
    }

    SDL_RenderPresent(pRenderer);

    SDL_Event event;
    bool isRun = true;
    while(isRun)
    {
        SDL_WaitEvent(&event);
        switch (event.type) {
            case SDL_QUIT:{
                isRun = false;
            }break;
            default:{
            }break;
        }
    }
    SDL_DestroyTexture(pTexture);
    SDL_FreeSurface(pSurface);
    SDL_RenderClear(pRenderer);
    SDL_DestroyWindow(pWindow);
    SDL_Quit();
    return 0;
}

在这里插入图片描述

CMAKE 配置SDL库

在CMakeLists.txt文件中添加如下代码
include_directories(./SDL2/include)
link_directories(./SDL2/lib)
add_executable($(project_name) main.cpp)
target_link_libraries(sdl2_test1 SDL2)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

代码海贼团船长

你的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值