gdiplus: Avoid not necessary memory allocation in GdipCreateBitmapFromHICON.

This commit is contained in:
Dmitry Timoshkov 2013-01-16 17:18:30 +08:00 committed by Alexandre Julliard
parent 31e8976910
commit 0d0f05e523
1 changed files with 12 additions and 33 deletions

View File

@ -1628,13 +1628,12 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromHICON(HICON hicon, GpBitmap** bitmap)
ICONINFO iinfo; ICONINFO iinfo;
BITMAP bm; BITMAP bm;
int ret; int ret;
UINT width, height; UINT width, height, stride;
GpRect rect; GpRect rect;
BitmapData lockeddata; BitmapData lockeddata;
HDC screendc; HDC screendc;
BOOL has_alpha; BOOL has_alpha;
int x, y; int x, y;
BYTE *bits;
BITMAPINFOHEADER bih; BITMAPINFOHEADER bih;
DWORD *src; DWORD *src;
BYTE *dst_row; BYTE *dst_row;
@ -1654,24 +1653,13 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromHICON(HICON hicon, GpBitmap** bitmap)
} }
width = bm.bmWidth; width = bm.bmWidth;
height = iinfo.hbmColor ? abs(bm.bmHeight) : abs(bm.bmHeight) / 2;
stride = width * 4;
if (iinfo.hbmColor) stat = GdipCreateBitmapFromScan0(width, height, stride, PixelFormat32bppARGB, NULL, bitmap);
height = abs(bm.bmHeight);
else /* combined bitmap + mask */
height = abs(bm.bmHeight) / 2;
bits = HeapAlloc(GetProcessHeap(), 0, 4*width*height);
if (!bits) {
DeleteObject(iinfo.hbmColor);
DeleteObject(iinfo.hbmMask);
return OutOfMemory;
}
stat = GdipCreateBitmapFromScan0(width, height, 0, PixelFormat32bppARGB, NULL, bitmap);
if (stat != Ok) { if (stat != Ok) {
DeleteObject(iinfo.hbmColor); DeleteObject(iinfo.hbmColor);
DeleteObject(iinfo.hbmMask); DeleteObject(iinfo.hbmMask);
HeapFree(GetProcessHeap(), 0, bits);
return stat; return stat;
} }
@ -1684,7 +1672,6 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromHICON(HICON hicon, GpBitmap** bitmap)
if (stat != Ok) { if (stat != Ok) {
DeleteObject(iinfo.hbmColor); DeleteObject(iinfo.hbmColor);
DeleteObject(iinfo.hbmMask); DeleteObject(iinfo.hbmMask);
HeapFree(GetProcessHeap(), 0, bits);
GdipDisposeImage((GpImage*)*bitmap); GdipDisposeImage((GpImage*)*bitmap);
return stat; return stat;
} }
@ -1704,14 +1691,14 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromHICON(HICON hicon, GpBitmap** bitmap)
screendc = GetDC(0); screendc = GetDC(0);
if (iinfo.hbmColor) if (iinfo.hbmColor)
{ {
GetDIBits(screendc, iinfo.hbmColor, 0, height, bits, (BITMAPINFO*)&bih, DIB_RGB_COLORS); GetDIBits(screendc, iinfo.hbmColor, 0, height, lockeddata.Scan0, (BITMAPINFO*)&bih, DIB_RGB_COLORS);
if (bm.bmBitsPixel == 32) if (bm.bmBitsPixel == 32)
{ {
has_alpha = FALSE; has_alpha = FALSE;
/* If any pixel has a non-zero alpha, ignore hbmMask */ /* If any pixel has a non-zero alpha, ignore hbmMask */
src = (DWORD*)bits; src = (DWORD*)lockeddata.Scan0;
for (x=0; x<width && !has_alpha; x++) for (x=0; x<width && !has_alpha; x++)
for (y=0; y<height && !has_alpha; y++) for (y=0; y<height && !has_alpha; y++)
if ((*src++ & 0xff000000) != 0) if ((*src++ & 0xff000000) != 0)
@ -1721,24 +1708,16 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromHICON(HICON hicon, GpBitmap** bitmap)
} }
else else
{ {
GetDIBits(screendc, iinfo.hbmMask, 0, height, bits, (BITMAPINFO*)&bih, DIB_RGB_COLORS); GetDIBits(screendc, iinfo.hbmMask, 0, height, lockeddata.Scan0, (BITMAPINFO*)&bih, DIB_RGB_COLORS);
has_alpha = FALSE; has_alpha = FALSE;
} }
/* copy the image data to the Bitmap */
src = (DWORD*)bits;
dst_row = lockeddata.Scan0;
for (y=0; y<height; y++)
{
memcpy(dst_row, src, width*4);
src += width;
dst_row += lockeddata.Stride;
}
if (!has_alpha) if (!has_alpha)
{ {
if (iinfo.hbmMask) if (iinfo.hbmMask)
{ {
BYTE *bits = HeapAlloc(GetProcessHeap(), 0, height * stride);
/* read alpha data from the mask */ /* read alpha data from the mask */
if (iinfo.hbmColor) if (iinfo.hbmColor)
GetDIBits(screendc, iinfo.hbmMask, 0, height, bits, (BITMAPINFO*)&bih, DIB_RGB_COLORS); GetDIBits(screendc, iinfo.hbmMask, 0, height, bits, (BITMAPINFO*)&bih, DIB_RGB_COLORS);
@ -1760,11 +1739,13 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromHICON(HICON hicon, GpBitmap** bitmap)
} }
dst_row += lockeddata.Stride; dst_row += lockeddata.Stride;
} }
HeapFree(GetProcessHeap(), 0, bits);
} }
else else
{ {
/* set constant alpha of 255 */ /* set constant alpha of 255 */
dst_row = bits; dst_row = lockeddata.Scan0;
for (y=0; y<height; y++) for (y=0; y<height; y++)
{ {
dst = (DWORD*)dst_row; dst = (DWORD*)dst_row;
@ -1782,8 +1763,6 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromHICON(HICON hicon, GpBitmap** bitmap)
GdipBitmapUnlockBits(*bitmap, &lockeddata); GdipBitmapUnlockBits(*bitmap, &lockeddata);
HeapFree(GetProcessHeap(), 0, bits);
return Ok; return Ok;
} }