From: Dmitry Timoshkov dmitry@baikal.ru
Application in the bug 39474 depends on this (GetObject/bmBits should not be NULL, otherwise it crashes). Also, since CreateDIBSection doesn't support RLE compressed bitmaps it's necessary to decompress it in memory in advance.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=39474 Signed-off-by: Dmitry Timoshkov dmitry@baikal.ru --- dlls/oleaut32/olepicture.c | 72 +++++++++----------------------- dlls/oleaut32/tests/olepicture.c | 14 ++++++- 2 files changed, 32 insertions(+), 54 deletions(-)
diff --git a/dlls/oleaut32/olepicture.c b/dlls/oleaut32/olepicture.c index a461d28f6eb..8278ec1f2f8 100644 --- a/dlls/oleaut32/olepicture.c +++ b/dlls/oleaut32/olepicture.c @@ -981,40 +981,13 @@ static HRESULT WINAPI OLEPictureImpl_IsDirty( return E_NOTIMPL; }
-static HRESULT OLEPictureImpl_LoadDIB(OLEPictureImpl *This, BYTE *xbuf, ULONG xread) -{ - BITMAPFILEHEADER *bfh = (BITMAPFILEHEADER*)xbuf; - BITMAPINFO *bi = (BITMAPINFO*)(bfh+1); - HDC hdcref; - - /* Does not matter whether this is a coreheader or not, we only use - * components which are in both - */ - hdcref = GetDC(0); - This->desc.bmp.hbitmap = CreateDIBitmap( - hdcref, - &(bi->bmiHeader), - CBM_INIT, - xbuf+bfh->bfOffBits, - bi, - DIB_RGB_COLORS - ); - ReleaseDC(0, hdcref); - if (This->desc.bmp.hbitmap == 0) - return E_FAIL; - This->desc.picType = PICTYPE_BITMAP; - OLEPictureImpl_SetBitmap(This); - return S_OK; -} - static HRESULT OLEPictureImpl_LoadWICSource(OLEPictureImpl *This, IWICBitmapSource *src) { HRESULT hr; BITMAPINFOHEADER bih; - HDC hdcref; UINT width, height; UINT stride, buffersize; - LPBYTE bits=NULL; + BYTE *bits, *mask = NULL; WICRect rc; IWICBitmapSource *real_source; UINT x, y; @@ -1042,34 +1015,28 @@ static HRESULT OLEPictureImpl_LoadWICSource(OLEPictureImpl *This, IWICBitmapSour stride = 4 * width; buffersize = stride * height;
- bits = malloc(buffersize); - if (!bits) + mask = malloc(buffersize); + if (!mask) { hr = E_OUTOFMEMORY; goto end; }
+ This->desc.bmp.hbitmap = CreateDIBSection(0, (BITMAPINFO*)&bih, DIB_RGB_COLORS, (void **)&bits, NULL, 0); + if (This->desc.bmp.hbitmap == 0) + { + hr = E_FAIL; + goto end; + } + rc.X = 0; rc.Y = 0; rc.Width = width; rc.Height = height; hr = IWICBitmapSource_CopyPixels(real_source, &rc, stride, buffersize, bits); if (FAILED(hr)) - goto end; - - hdcref = GetDC(0); - This->desc.bmp.hbitmap = CreateDIBitmap( - hdcref, - &bih, - CBM_INIT, - bits, - (BITMAPINFO*)&bih, - DIB_RGB_COLORS); - - if (This->desc.bmp.hbitmap == 0) { - hr = E_FAIL; - ReleaseDC(0, hdcref); + DeleteObject(This->desc.bmp.hbitmap); goto end; }
@@ -1083,23 +1050,25 @@ static HRESULT OLEPictureImpl_LoadWICSource(OLEPictureImpl *This, IWICBitmapSour if((*pixel & 0x80000000) == 0) { has_alpha = TRUE; - *pixel = black; + *(DWORD *)(mask + stride * y + 4 * x) = black; } else - *pixel = white; + *(DWORD *)(mask + stride * y + 4 * x) = white; } }
if (has_alpha) { - HDC hdcBmp, hdcXor, hdcMask; + HDC hdcref, hdcBmp, hdcXor, hdcMask; HBITMAP hbmoldBmp, hbmoldXor, hbmoldMask;
+ hdcref = GetDC(0); + This->hbmXor = CreateDIBitmap( hdcref, &bih, CBM_INIT, - bits, + mask, (BITMAPINFO*)&bih, DIB_RGB_COLORS ); @@ -1124,12 +1093,11 @@ static HRESULT OLEPictureImpl_LoadWICSource(OLEPictureImpl *This, IWICBitmapSour DeleteDC(hdcBmp); DeleteDC(hdcXor); DeleteDC(hdcMask); + ReleaseDC(0, hdcref); }
- ReleaseDC(0, hdcref); - end: - free(bits); + free(mask); IWICBitmapSource_Release(real_source); return hr; } @@ -1494,7 +1462,7 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface, IStream *pStm) hr = OLEPictureImpl_LoadWICDecoder(This, &CLSID_WICJpegDecoder, xbuf, xread); break; case BITMAP_FORMAT_BMP: /* Bitmap */ - hr = OLEPictureImpl_LoadDIB(This, xbuf, xread); + hr = OLEPictureImpl_LoadWICDecoder(This, &CLSID_WICBmpDecoder, xbuf, xread); break; case BITMAP_FORMAT_PNG: /* PNG */ hr = OLEPictureImpl_LoadWICDecoder(This, &CLSID_WICPngDecoder, xbuf, xread); diff --git a/dlls/oleaut32/tests/olepicture.c b/dlls/oleaut32/tests/olepicture.c index 1cdea2ec2b9..eb9685a0f7d 100644 --- a/dlls/oleaut32/tests/olepicture.c +++ b/dlls/oleaut32/tests/olepicture.c @@ -97,7 +97,7 @@ static const unsigned char pngimage[285] = { 0xe7,0x00,0x00,0x00,0x00,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 };
-/* 1x1 pixel bmp */ +/* 1bpp BI_RGB 1x1 pixel bmp */ static const unsigned char bmpimage[66] = { 0x42,0x4d,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x28,0x00, 0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00, @@ -106,6 +106,15 @@ static const unsigned char bmpimage[66] = { 0x00,0x00 };
+/* 8bpp BI_RLE8 1x1 pixel bmp */ +static const unsigned char bmpimage_rle8[] = { +0x42,0x4d,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x28,0x00, +0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00, +0x00,0x00,0x04,0x00,0x00,0x00,0x12,0x0b,0x00,0x00,0x12,0x0b,0x00,0x00,0x02,0x00, +0x00,0x00,0x02,0x00,0x00,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0x00,0x01, +0x00,0x00 +}; + /* 2x2 pixel gif */ static const unsigned char gif4pixel[42] = { 0x47,0x49,0x46,0x38,0x37,0x61,0x02,0x00,0x02,0x00,0xa1,0x00,0x00,0x00,0x00,0x00, @@ -239,7 +248,7 @@ test_pic_with_stream(LPSTREAM stream, unsigned int imgsize) { BITMAP bmp; GetObjectA(UlongToHandle(handle), sizeof(BITMAP), &bmp); - todo_wine ok(bmp.bmBits != 0, "not a dib\n"); + ok(bmp.bmBits != 0, "not a dib\n"); }
width = 0; @@ -1628,6 +1637,7 @@ START_TEST(olepicture) test_pic(gifimage, sizeof(gifimage)); test_pic(jpgimage, sizeof(jpgimage)); test_pic(bmpimage, sizeof(bmpimage)); + test_pic(bmpimage_rle8, sizeof(bmpimage_rle8)); test_pic(gif4pixel, sizeof(gif4pixel)); /* FIXME: No PNG support in Windows... */ if (0) test_pic(pngimage, sizeof(pngimage));