Skip to content

Commit

Permalink
windows: fix BITMAPINFOHEADER values when getting bitmap from Clipboard
Browse files Browse the repository at this point in the history
  • Loading branch information
evertonse authored and slouken committed Dec 24, 2024
1 parent af2dbbc commit 8a0f649
Showing 1 changed file with 48 additions and 2 deletions.
50 changes: 48 additions & 2 deletions src/video/windows/SDL_windowsclipboard.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,51 @@
// Assume we can directly read and write BMP fields without byte swapping
SDL_COMPILE_TIME_ASSERT(verify_byte_order, SDL_BYTEORDER == SDL_LIL_ENDIAN);

static int WIN_GetPixelDataOffset(BITMAPINFOHEADER bih)
{
int offset = 0;
// biSize Specifies the number of bytes required by the structure
// We expect to always be 40 because it should be packed
if (40 == bih.biSize && 40 == sizeof(BITMAPINFOHEADER))
{
//
// biBitCount Specifies the number of bits per pixel.
// Might exist some bit masks *after* the header and *before* the pixel offset
// we're looking, but only if we have more than
// 8 bits per pixel, so we need to ajust for that
//
if (bih.biBitCount > 8)
{
// If bih.biCompression is RBG we should NOT offset more

if (bih.biCompression == BI_BITFIELDS)
{
offset += 3 * sizeof(RGBQUAD);
} else if (bih.biCompression == 6 /* BI_ALPHABITFIELDS */) {
// Not common, but still right
offset += 4 * sizeof(RGBQUAD);
}
}
}

//
// biClrUsed Specifies the number of color indices in the color table that are actually used by the bitmap.
// If this value is zero, the bitmap uses the maximum number of colors
// corresponding to the value of the biBitCount member for the compression mode specified by biCompression.
// If biClrUsed is nonzero and the biBitCount member is less than 16
// the biClrUsed member specifies the actual number of colors
//
if (bih.biClrUsed > 0) {
offset += bih.biClrUsed * sizeof(RGBQUAD);
} else {
if (bih.biBitCount < 16) {
offset = offset + (sizeof(RGBQUAD) << bih.biBitCount);
}
}
return bih.biSize + offset;
}


static BOOL WIN_OpenClipboard(SDL_VideoDevice *_this)
{
// Retry to open the clipboard in case another application has it open
Expand Down Expand Up @@ -114,16 +159,17 @@ static void *WIN_ConvertDIBtoBMP(HANDLE hMem, size_t *size)
BITMAPINFOHEADER *pbih = (BITMAPINFOHEADER *)dib;
size_t bih_size = pbih->biSize + pbih->biClrUsed * sizeof(RGBQUAD);
size_t dib_size = bih_size + pbih->biSizeImage;
int pixel_offset = WIN_GetPixelDataOffset(*pbih);
if (dib_size <= mem_size) {
size_t bmp_size = sizeof(BITMAPFILEHEADER) + dib_size;
size_t bmp_size = sizeof(BITMAPFILEHEADER) + mem_size;
bmp = SDL_malloc(bmp_size);
if (bmp) {
BITMAPFILEHEADER *pbfh = (BITMAPFILEHEADER *)bmp;
pbfh->bfType = BFT_BITMAP;
pbfh->bfSize = (DWORD)bmp_size;
pbfh->bfReserved1 = 0;
pbfh->bfReserved2 = 0;
pbfh->bfOffBits = (DWORD)(sizeof(BITMAPFILEHEADER) + bih_size);
pbfh->bfOffBits = (DWORD)(sizeof(BITMAPFILEHEADER) + pixel_offset);
SDL_memcpy((Uint8 *)bmp + sizeof(BITMAPFILEHEADER), dib, dib_size);
*size = bmp_size;
}
Expand Down

0 comments on commit 8a0f649

Please sign in to comment.