gdiplus: Explicitly copy the bits from dib sections to new bitmaps.
On Windows, GdipCreateBitmapFromHBITMAP creates a copy of the bitmap, not a reference. Currently, we match this behavior, but this is only because we cannot yet create bitmap objects that reference existing memory. If GdipCreateBitmapFromScan0 were fixed to do this, FromHBITMAP would break. Therefore, we always pass NULL to FromScan0 so that it allocates new memory for the bitmap.
This commit is contained in:
parent
9823c23927
commit
3424dac386
|
@ -2659,7 +2659,8 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromHBITMAP(HBITMAP hbm, HPALETTE hpal, GpBi
|
|||
BITMAP bm;
|
||||
GpStatus retval;
|
||||
PixelFormat format;
|
||||
BYTE* bits;
|
||||
BitmapData lockeddata;
|
||||
INT y;
|
||||
|
||||
TRACE("%p %p %p\n", hbm, hpal, bitmap);
|
||||
|
||||
|
@ -2700,16 +2701,32 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromHBITMAP(HBITMAP hbm, HPALETTE hpal, GpBi
|
|||
return InvalidParameter;
|
||||
}
|
||||
|
||||
if (bm.bmBits)
|
||||
bits = (BYTE*)bm.bmBits + (bm.bmHeight - 1) * bm.bmWidthBytes;
|
||||
else
|
||||
{
|
||||
FIXME("can only get image data from DIB sections\n");
|
||||
bits = NULL;
|
||||
}
|
||||
retval = GdipCreateBitmapFromScan0(bm.bmWidth, bm.bmHeight, 0,
|
||||
format, NULL, bitmap);
|
||||
|
||||
retval = GdipCreateBitmapFromScan0(bm.bmWidth, bm.bmHeight, -bm.bmWidthBytes,
|
||||
format, bits, bitmap);
|
||||
if (retval == Ok)
|
||||
{
|
||||
retval = GdipBitmapLockBits(*bitmap, NULL, ImageLockModeWrite,
|
||||
format, &lockeddata);
|
||||
if (retval == Ok)
|
||||
{
|
||||
if (bm.bmBits)
|
||||
{
|
||||
for (y=0; y<bm.bmHeight; y++)
|
||||
{
|
||||
memcpy((BYTE*)lockeddata.Scan0+lockeddata.Stride*y,
|
||||
(BYTE*)bm.bmBits+bm.bmWidthBytes*(bm.bmHeight-1-y),
|
||||
bm.bmWidthBytes);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FIXME("can only get image data from DIB sections\n");
|
||||
}
|
||||
|
||||
GdipBitmapUnlockBits(*bitmap, &lockeddata);
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
|
|
@ -465,6 +465,7 @@ static void test_GdipCreateBitmapFromHBITMAP(void)
|
|||
const REAL HEIGHT2 = 20;
|
||||
HDC hdc;
|
||||
BITMAPINFO bmi;
|
||||
BYTE *bits;
|
||||
|
||||
stat = GdipCreateBitmapFromHBITMAP(NULL, NULL, NULL);
|
||||
expect(InvalidParameter, stat);
|
||||
|
@ -504,16 +505,26 @@ static void test_GdipCreateBitmapFromHBITMAP(void)
|
|||
bmi.bmiHeader.biPlanes = 1;
|
||||
bmi.bmiHeader.biCompression = BI_RGB;
|
||||
|
||||
hbm = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, NULL, NULL, 0);
|
||||
hbm = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
|
||||
ok(hbm != NULL, "CreateDIBSection failed\n");
|
||||
|
||||
bits[0] = 0;
|
||||
|
||||
stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm);
|
||||
expect(Ok, stat);
|
||||
expect(Ok, GdipGetImageDimension((GpImage*) gpbm, &width, &height));
|
||||
expectf(WIDTH1, width);
|
||||
expectf(HEIGHT1, height);
|
||||
if (stat == Ok)
|
||||
{
|
||||
/* test whether writing to the bitmap affects the original */
|
||||
stat = GdipBitmapSetPixel(gpbm, 0, 0, 0xffffffff);
|
||||
expect(Ok, stat);
|
||||
|
||||
expect(0, bits[0]);
|
||||
|
||||
GdipDisposeImage((GpImage*)gpbm);
|
||||
}
|
||||
|
||||
LogPal = GdipAlloc(sizeof(LOGPALETTE));
|
||||
ok(LogPal != NULL, "unable to allocate LOGPALETTE\n");
|
||||
|
|
Loading…
Reference in New Issue