Проблема с SDL_GetRGBA, возвращающей мусор при вызове на некоторых, но не на всех поверхностях - PullRequest
0 голосов
/ 05 марта 2019

У меня есть изображение 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), но произошло то же самое.

Я в своем уме.Это не конец света, так как мне не нужно его восстанавливать, как только он будет создан.Я все еще могу загрузить целую версию пользовательского файла просто отлично.Это просто действительно неудовлетворительно.
Так что, если кто-то не выяснит, что здесь происходит, я буду продолжать и продолжать делать другие части программы.

...