From: Esme Povirk <esme@codeweavers.com> Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=40409 --- dlls/gdiplus/image.c | 65 +++++++++++++++++++++++++++++++------- dlls/gdiplus/tests/image.c | 2 -- 2 files changed, 53 insertions(+), 14 deletions(-) diff --git a/dlls/gdiplus/image.c b/dlls/gdiplus/image.c index 6e99cd30db6..e6b460e7a3c 100644 --- a/dlls/gdiplus/image.c +++ b/dlls/gdiplus/image.c @@ -1468,9 +1468,8 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromGdiDib(GDIPCONST BITMAPINFO* info, VOID *bits, GpBitmap **bitmap) { DWORD height, stride; - HBITMAP hbm; - void *bmbits; - GpStatus status; + PixelFormat format; + BYTE *scan0; TRACE("(%p, %p, %p)\n", info, bits, bitmap); @@ -1480,20 +1479,62 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromGdiDib(GDIPCONST BITMAPINFO* info, if (info->bmiHeader.biSize < sizeof(BITMAPINFOHEADER)) return InvalidParameter; - hbm = CreateDIBSection(0, info, DIB_RGB_COLORS, &bmbits, NULL, 0); - if (!hbm) - return InvalidParameter; - height = abs(info->bmiHeader.biHeight); stride = ((info->bmiHeader.biWidth * info->bmiHeader.biBitCount + 31) >> 3) & ~3; - TRACE("height %lu, stride %lu, image size %lu\n", height, stride, height * stride); + scan0 = bits; - memcpy(bmbits, bits, height * stride); + if (info->bmiHeader.biHeight > 0) + { + scan0 = scan0 + (height - 1) * stride; + stride = -stride; + } - status = GdipCreateBitmapFromHBITMAP(hbm, NULL, bitmap); - DeleteObject(hbm); + switch (info->bmiHeader.biBitCount) + { + case 1: + format = PixelFormat1bppIndexed; + break; + case 4: + format = PixelFormat4bppIndexed; + break; + case 8: + format = PixelFormat8bppIndexed; + break; + case 16: + { + if (info->bmiHeader.biCompression == BI_RGB) + { + format = PixelFormat16bppRGB555; + break; + } + if (info->bmiHeader.biCompression == BI_BITFIELDS && info->bmiHeader.biSize >= FIELD_OFFSET(BITMAPV4HEADER, bV4AlphaMask)) + { + const BITMAPV4HEADER *header = (const BITMAPV4HEADER*)info; + if (header->bV4RedMask == 0x7c00 && header->bV4GreenMask == 0x3e0 && header->bV4BlueMask == 0x1f) + { + format = PixelFormat16bppRGB555; + break; + } + if (header->bV4RedMask == 0xf800 && header->bV4GreenMask == 0x7e0 && header->bV4BlueMask == 0x1f) + { + format = PixelFormat16bppRGB565; + break; + } + } + return InvalidParameter; + } + case 24: + format = PixelFormat24bppRGB; + break; + case 32: + format = PixelFormat32bppRGB; + break; + default: + FIXME("don't know how to handle %d bpp\n", info->bmiHeader.biBitCount); + return InvalidParameter; + } - return status; + return GdipCreateBitmapFromScan0(info->bmiHeader.biWidth, height, stride, format, scan0, bitmap); } /* FIXME: no icm */ diff --git a/dlls/gdiplus/tests/image.c b/dlls/gdiplus/tests/image.c index 011bc116cd8..7346ba94880 100644 --- a/dlls/gdiplus/tests/image.c +++ b/dlls/gdiplus/tests/image.c @@ -290,12 +290,10 @@ static void check_bitmap_bits_(GpBitmap *bitmap, UINT width, UINT height, int st ok_(file, line)(stat == Ok, "GdipBitmapLockBits failed, status=%i\n", stat); ok_(file, line)(width == lock.Width, "BitmapData.Width == %d, expected %d\n", lock.Width, width); ok_(file, line)(height == lock.Height, "BitmapData.Height == %d, expected %d\n", lock.Height, height); -todo_wine_if(stride < 0) ok_(file, line)(stride == lock.Stride, "BitmapData.Stride == %i, expected %i\n", lock.Stride, stride); ok_(file, line)(format == lock.PixelFormat, "BitmapData.PixelFormat == %x, expected %x\n", lock.PixelFormat, format); if (scan0) { -todo_wine ok_(file, line)(scan0 == lock.Scan0, "BitmapData.Scan0 == %p, expected %p\n", lock.Scan0, scan0); } ok_(file, line)(lock.Reserved == 0, "BitmapData.Reserved == %p, expected 0\n", (void*)lock.Reserved); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10652