在C++的SDL2窗口中显示.bmp时出现问题

ha5z0ras  于 2023-01-03  发布在  其他
关注(0)|答案(2)|浏览(208)

第一个问题,我真的需要帮助。所以我试着去学习
SDL 2 API在C++上。我使用的是raspberry pi 3模型B。我第一次在Youtube上学习教程(CodingMadeEasy更具体),但现在我在学习lazyfoo的教程。我复制了CME的代码,并尝试显示图像(.bmp),但窗口什么也没有显示,SDL_GetError()也没有报告任何错误。我想肯定有
我写的代码可能有问题,或者我从网上下载的图像可能不是.bmp,所以我去lazyfoo的教程http://lazyfoo.net/tutorials/SDL/02_getting_an_image_on_the_screen/index.php下载了源代码和.bmp文件,但是当我运行它时,我得到了相同的输出:一个空白窗口和SDL_GetError()在控制台上不报告任何内容。

/*This source code copyrighted by Lazy Foo' Productions 

(2004-2015)
and may not be redistributed without written permission.*/

//Using SDL and standard IO
#include <SDL2/SDL.h>
#include <stdio.h>

//Screen dimension constants
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;

//Starts up SDL and creates window
bool init();

//Loads media
bool loadMedia();

//Frees media and shuts down SDL
void close();

//The window we'll be rendering to
SDL_Window* gWindow = NULL;

//The surface contained by the window
SDL_Surface* gScreenSurface = NULL;

//The image we will load and show on the screen
SDL_Surface* gHelloWorld = NULL;

bool init()
{
    //Initialization flag
    bool success = true;

    //Initialize SDL
    if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
    {
        printf( "SDL could not initialize! SDL_Error: %s\n", SDL_GetError() );
        success = false;
    }
    else
    {
        //Create window
        gWindow = SDL_CreateWindow( "SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN );
        if( gWindow == NULL )
        {
            printf( "Window could not be created! SDL_Error: %s\n", SDL_GetError() );
            success = false;
        }
        else
        {
            //Get window surface
            gScreenSurface = SDL_GetWindowSurface( gWindow );
        }
    }

    return success;
}

bool loadMedia()
{
    //Loading success flag
    bool success = true;

    //Load splash image
    gHelloWorld = SDL_LoadBMP( "02_getting_an_image_on_the_screen/hello_world.bmp" );
    if( gHelloWorld == NULL )
    {
        printf( "Unable to load image %s! SDL Error: %s\n", "02_getting_an_image_on_the_screen/hello_world.bmp", SDL_GetError() );
        success = false;
    }

    return success;
}

void close()
{
    //Deallocate surface
    SDL_FreeSurface( gHelloWorld );
    gHelloWorld = NULL;

    //Destroy window
    SDL_DestroyWindow( gWindow );
    gWindow = NULL;

    //Quit SDL subsystems
    SDL_Quit();
}

int main( int argc, char* args[] )
{
    //Start up SDL and create window
    if( !init() )
    {
        printf( "Failed to initialize!\n" );
    }
    else
    {
        //Load media
        if( !loadMedia() )
        {
            printf( "Failed to load media!\n" );
        }
        else
        {
            //Apply the image
            SDL_BlitSurface( gHelloWorld, NULL, gScreenSurface, NULL );

            //Update the surface
            SDL_UpdateWindowSurface( gWindow );

            //Wait two seconds
            SDL_Delay( 2000 );
        }
    }

    //Free resources and close SDL
    close();

    return 0;
}

如果你想要.bmp文件,请访问上面的链接并下载源代码和文件。它不让我上传它。下面是我得到的输出:Output。这个透明的,灰色的窗口。我用gnu c++编译器编译的

g++ 02_getting_an_image_on_the_screen.cpp -w -lSDL2 -o hl

然后得到那个透明的灰色窗口。我猜它是透明的,因为我的终端是这样配置的。为了看看问题是什么,我删除了.bmp,看看sdl是否报告了一个错误,它报告了,这意味着它能够读取.bmp,当它在正确的位置,只是不能显示它。我搜索了谷歌几个小时,一无所获。在堆栈溢出,最接近我的问题是这个SDL window does not show我甚至试过轮询事件,以便给予系统运行事件循环的机会,就像这里建议的那样,但是不管窗口打开多久,.bmp没有显示。更奇怪的是,这种情况不是我第一次遇到。我一年前尝试学习SDL 2,但当时发生了同样的事情。我当时使用的是一台廉价的Windows 10笔记本电脑,内存为2GB,并且使用code::blocks(mingw编译器版本),同样的情况也发生了,只是窗口不是透明的,而是白色的,就像你在Windows中使用sdl创建一个窗口而不显示任何内容一样。出于某种原因,代码块不允许我将窗口设置为nullptr,说它无法识别它是什么,所以我不得不将其设置为NULL。因此,我认为窗口不显示.bmp也是编译器的错。所以我下载了Microsoft Visual Studio 2015,但结果是一样的:没有图像显示。在这一点上,我放弃了,但现在我回来了,因为我有一个新的机器(rpi模型3 b)和一个新的编译器(gnu c/c++)上认为SDL不会再困扰我,但SDL似乎没有给予。我真的需要帮助。是的,.bmp是在正确的位置,我已经在代码中包含了它的正确名称,记住我已经尝试在2台机器,3个编译器上这样做了,2个非常不同的操作系统和2个不同的CPU架构(armv71和x86),在这一点上它变得令人沮丧如果SDL 2允许的话,我有一些很棒的想法,可以很容易地实现。很抱歉发了这么长的帖子,任何帮助都是非常感谢的。谢谢。

brvekthn

brvekthn1#

你的代码在我的iMac上运行良好。我所做的唯一更改如下,所以也许可以尝试做同样的更改,看看它是否适合你。
首先,有许多不同类型的BMP文件,您可能已经拥有了一个在您的图片查看器应用程序中运行良好的文件,但SDL对加载它感到“不高兴”。为了消除疑虑,请使用ImageMagick创建您自己的BMP文件,然后您可以确保您拥有一个好的文件。我在Terminal中使用了这个:

convert -size 640x480 gradient:red-cyan image.bmp

其次,在任何 “集成开发环境” 之外运行您的程序,即仅从终端运行,并且所有映像都在当前目录中(没有路径)并且名称中都没有空格。原因是IDE会对事件循环和屏幕更新造成严重破坏,IDE经常看起来运行一个程序,但实际上运行的是/some/where/else/Debug/program,这会弄乱您打开的文件的路径,例如您的"02_getting_an_image_on_the_screen/hello_world.bmp",这也意味着目录分隔符不会导致问题。
第三,考虑使用pkgconfig来获取头文件路径和库。例如,在我的Mac上,它添加了一个我可能没有意识到的线程安全定义:

pkg-config --cflags --libs sdl2

示例输出

-D_THREAD_SAFE -I/usr/local/include/SDL2 -L/usr/local/lib -lSDL2

因此,为了编译,我用途:

g++ main.cpp $(pkg-config --cflags --libs sdl2) -o main
blmhpbnm

blmhpbnm2#

如果我回答这个老问题时违反了某些规则,请原谅,但它帮助我找到了一个解决我所面临的 * 类似 * 问题的方法。在9/17/22版本的Lazy Foo SDL 2指南之后,我有几乎完全相同的代码,只是主要功能不同。以下是我编辑的代码,但没有删除其含义。

int main(int argc, char *argv[])
{
    if (game_init() == 0) {
        printf("Failed to initialize game!\n");
        exit(EXIT_FAILURE);
    }

    if (game_load_media() == 0) {
        printf("Failed to load media!\n");
        exit(EXIT_FAILURE);
    }

    SDL_BlitSurface(gHelloSurface, NULL, gScreenSurface, NULL);

    SDL_UpdateWindowSurface(gWindow);

    SDL_Event e;
    int quit = 0;
    while( quit == 0 ) {
        SDL_PollEvent( &e );
        if( e.type == SDL_QUIT )
            quit = true;
    }

    game_close();

    return 0;
}

问题是窗口有时是透明的,而有时它正确加载图像并显示BMP图像。通过对SDL_WindowFlags的实验和函数调用的安排,我发现通过延迟:

SDL_BlitSurface(gHelloSurface, NULL, gScreenSurface, NULL);
SDL_Delay(100);
SDL_UpdateWindowSurface(gWindow);

或者简单地将SDL_UpdateWindowSurface(gWindow);移到while循环中就解决了这个问题。作为一个初学者,我的猜测是有些东西没有及时初始化,但延迟调用或重复调用可以解决这个问题。
另外。我在X11上的KDE等离子体5.24.7、KDE框架5.92.0、Qt 5.15.3和内核5.15的Windows 10和Kubuntu 22.04上都遇到了这个问题。同样的黑客修复了这两个平台的问题。

相关问题