Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix SDL_GetClipboardData() for bitmap on Windows (SDL3). #11409

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

evertonse
Copy link

Description

Calling SDL_GetClipboardData on Windows may generate an incorrect bitmap file header for uncompressed bitmaps. This issue arises because SDL3 sometimes populates the BITMAPFILEHEADER with incorrect bfOffBits values, leading to corrupted bitmaps.

This PR addresses the problem by recalculating the pixel offset more accurately in the WIN_GetPixelDataOffset function, considering the presence of a palette array in the case of indexed bitmaps. Additionally, it corrects the usage of biSizeImage, taking into account that this value can sometimes be zero for uncompressed RGB bitmaps.

Quick Test

To test this, compile and run the code on Windows. Take a screenshot and press the V key, then check the generated clipboard.bmp file.

#include <SDL3/SDL.h>
#include <stdbool.h>

static void SDLTest_PasteScreenShot(void)
{
    const char *image_formats[] = {
        "image/png",
        "image/tiff",
        "image/bmp",
    };
    size_t i;

    for (i = 0; i < SDL_arraysize(image_formats); ++i) {
        size_t size;
        void *data = SDL_GetClipboardData(image_formats[i], &size);
        if (data) {
            char filename[16];
            SDL_IOStream *file;

            SDL_snprintf(filename, sizeof(filename), "clipboard.%s", image_formats[i] + 6);
            file = SDL_IOFromFile(filename, "w");
            if (file) {
                SDL_Log("Writing clipboard image to %s", filename);
                SDL_WriteIO(file, data, size);
                SDL_CloseIO(file);
            }
            SDL_free(data);
            return;
        }
    }
    SDL_Log("No supported screenshot data in the clipboard");
}

int main(int argc, char *argv[]) {
    SDL_Init(SDL_INIT_VIDEO);
    SDL_Window* window = SDL_CreateWindow("", 300, 200, 0);
    SDL_SetWindowTitle(window, "Window BMP Clipboard Test");
    bool quit = false;
    while (!quit) {
        SDL_Event event;
        while (SDL_PollEvent(&event)) {
            if (event.type == SDL_EVENT_KEY_DOWN && event.key.key == SDLK_V) {
                SDL_Log("Calling SDLTest_PasteScreenShot\n");
                SDLTest_PasteScreenShot();
            }
            else if (event.type == SDL_EVENT_QUIT) {
                quit = true;
            }
        }
        SDL_Delay(20);
    }
    SDL_Quit();
}

@slouken
Copy link
Collaborator

slouken commented Nov 4, 2024

Is this relevant for SDL_LoadBMP() as well?

@slouken slouken added this to the 3.2.0 milestone Nov 4, 2024
@evertonse
Copy link
Author

Is this relevant for SDL_LoadBMP() as well?

Probably, I'd have to check.
But if it calls SDL_GetClipboardData on windows, then it's relevant for sure.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants