首页 > 解决方案 > 在某些但不是所有表面上调用 SDL_GetRGBA 返回垃圾的问题

问题描述

我有一个用于创建纹理的 bmp 图像

SDL_Surface *temp = SDL_LoadBMP((RES + path + ".bmp").c_str());
surface = SDL_ConvertSurfaceFormat(temp,SDL_PIXELFORMAT_ABGR8888,0);
SDL_FreeSurface(temp);
texture = SDL_CreateTextureFromSurface(renderer, surface);

然后保存为自定义文件的一部分(之前和之后的一切都很好)

struct PixelRGBA{
    unsigned char r,g,b,a;
};  
PixelRGBA *surfaceToPixel(SDL_Surface *surface){
    PixelRGBA *ret = new PixelRGBA[surface->w * surface->h];
    SDL_LockSurface(surface);
    for (unsigned long long i = 0; i < surface->w * surface->h; i++){
        SDL_GetRGBA(
            ((unsigned int *)surface->pixels)[i],
            surface->format,
            &(ret[i].r),
            &(ret[i].g),
            &(ret[i].b),
            &(ret[i].a));
        std::cout << (unsigned int)ret[i].r << " " << (unsigned int)ret[i].g << " " << (unsigned int)ret[i].b << " " << (unsigned int)ret[i].a << std::endl;
    }
    SDL_UnlockSurface(surface);
    return ret;
}
#define BINO(x) write((char *)&x, sizeof(x))
std::ostream &operator<<(std::ostream &os, const PixelRGBA &obj)
{
    os.BINO(obj.r)
        .BINO(obj.g)
        .BINO(obj.b)
        .BINO(obj.a);
    return os;
}
//How it is saved
PixelRGBA *pixels = surfaceToPixel(obj.surface);
for (unsigned long long i = 0; i < w * h; i++)
    os << pixels[i];  

在下一次运行中,我加载这个自定义文件而不是 bmp

#define BINI(x) read((char *)&x, sizeof(x))
std::istream &operator>>(std::istream &is, PixelRGBA &obj)
{
    is.BINI(obj.r)
      .BINI(obj.g)
      .BINI(obj.b)
      .BINI(obj.a);
    return is;
}
SDL_Texture *textureFromSurface(SDL_Surface *surface)
{
    SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, surface);
    return texture;
}
SDL_Surface *surfaceFromRGBA(PixelRGBA *data, int w, int h)
{
    SDL_Surface *surface = SDL_CreateRGBSurfaceWithFormatFrom(
        (void *)data,
        w,
        h,
        sizeof(PixelRGBA)*8,
        sizeof(PixelRGBA) * w,
        SDL_PIXELFORMAT_ABGR8888);
    return surface;
}
//How it is loaded
PixelRGBA pixels[w * h];
for (unsigned long long i = 0; i < w * h; i++)
    is >> pixels[i];
obj.surface = surfaceFromRGBA(pixels, w, h);
obj.texture = textureFromSurface(obj.surface);  

到目前为止,一切都显示良好并且工作正常。
但是,当我尝试保存从内存创建的这个表面时——使用与从 bmp 创建的表面相同的方法——surfaceToRGBA 返回完整的垃圾,不是格式错误,只是垃圾(如果总是相似,第一个像素应该是 00 00 00 00 但变为 DD FF FF FF)。
我检查了 HxD 和 std::cout ,使用 bmp 一切都按预期工作,它完全按照我想要的方式保存。我可以很好地加载自定义文件。
只有当我尝试重新保存它时,它才会破坏并保存随机的东西。
但即便如此,文件大小也不会改变,其余部分仍然完好无损并按预期加载(使用 HxD 和调试器检查)。

文档说从表面创建纹理不会改变它,它没有被释放,也不能在其他任何地方访问。我花了一整天的时间尝试不同的事情,比如测试surfaceToPixel中的表面间距/像素大小是否有问题,surfaceFromRGBA格式(这就是为什么我知道它不是不匹配的格式,我已经看到了它的样子和它不能将 00 00 00 00 变成 DD FF FF FF fe) 但完全相同的事情发生了。

我无计可施。这不是世界末日,因为一旦它生成,我真的不需要重新保存它。我仍然可以很好地加载自定义文件的完整版本。只是真的很不满意。
因此,除非有人弄清楚 f 在这里发生了什么,否则我将继续前进并继续制作程序的其他部分。

标签: c++sdl-2

解决方案


推荐阅读