在 SDL2 中垂直翻转表面

Flipping a surface vertically in SDL2

我得到的最接近的是:

void Engine::flipSurfaceVertically(SDL_Surface* surface)
{
    SDL_LockSurface(surface);

    Uint8* pixels = reinterpret_cast<Uint8*>(surface->pixels);
    for (int k = 0; k < sizeof(Uint32); ++k)
    {
        for (int i = 0; i < surface->w; ++i)
        {
            for (int j = 0; j < surface->h / 2; ++j)
            {
                Uint32 currentPos = (j * surface->pitch) + (i * sizeof(Uint32)) + k;
                Uint32 target = ((surface->h - j - 1) * surface->pitch) + (i * sizeof(Uint32)) + k;
                Uint8 temp = pixels[target];
                pixels[target] = pixels[currentPos];
                pixels[currentPos] = temp;
            }
        }
    }

    SDL_UnlockSurface(surface);
}

但它并没有保持透明度。我怎样才能真正实现这一目标?

我不知道错误到底在哪里,我在我的机器上试过你的代码,它在我使用的图像上运行良好。我怀疑您的代码确实保留了透明度,但稍后在您的实现中将其删除。

无论如何,如果我可以建议改进您的代码:您不需要如此复杂的操作来垂直翻转表面。 SDL_Surface 结构以行优先顺序存储像素数据,这意味着 pixels 数组是一个行序列,其中每一行的大小为 pitch 字节。因此,要垂直翻转表面,您可以简单地遍历行并交换它们。这种方法的优点是它不需要像素格式的知识,所以它可以适用于所有图像类型(alpha 通道或非 alpha 通道),而且实现起来非常简单。

这是一个您可以编译和试验的最小示例:

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

void flip_surface(SDL_Surface* surface) 
{
    SDL_LockSurface(surface);
    
    int pitch = surface->pitch; // row size
    char* temp = new char[pitch]; // intermediate buffer
    char* pixels = (char*) surface->pixels;
    
    for(int i = 0; i < surface->h / 2; ++i) {
        // get pointers to the two rows to swap
        char* row1 = pixels + i * pitch;
        char* row2 = pixels + (surface->h - i - 1) * pitch;
        
        // swap rows
        memcpy(temp, row1, pitch);
        memcpy(row1, row2, pitch);
        memcpy(row2, temp, pitch);
    }
    
    delete[] temp;

    SDL_UnlockSurface(surface);
}

int main(int argc, char* argv[]) 
{
    SDL_Init(SDL_INIT_VIDEO);
    
    SDL_Surface* surface = IMG_Load("image.png");
    flip_surface(surface);
    IMG_SavePNG(surface, "result.png");
    
    SDL_Quit();
    
    return 0;
}