Vincent Povirk : gdiplus: Reimplement GdipCreateBitmapFromHICON based on RGBA bitmaps.
Alexandre Julliard
julliard at winehq.org
Sat Aug 29 11:36:27 CDT 2009
Module: wine
Branch: master
Commit: cb3ee716a2b3e2bafd102c82574df5baaf469a4a
URL: http://source.winehq.org/git/wine.git/?a=commit;h=cb3ee716a2b3e2bafd102c82574df5baaf469a4a
Author: Vincent Povirk <vincent at codeweavers.com>
Date: Mon Aug 24 17:05:24 2009 -0500
gdiplus: Reimplement GdipCreateBitmapFromHICON based on RGBA bitmaps.
---
dlls/gdiplus/image.c | 170 +++++++++++++++++++++++++++++++++++++++++++-------
1 files changed, 146 insertions(+), 24 deletions(-)
diff --git a/dlls/gdiplus/image.c b/dlls/gdiplus/image.c
index 164ab29..730d981 100644
--- a/dlls/gdiplus/image.c
+++ b/dlls/gdiplus/image.c
@@ -625,48 +625,170 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromGraphics(INT width, INT height,
GpStatus WINGDIPAPI GdipCreateBitmapFromHICON(HICON hicon, GpBitmap** bitmap)
{
- HICON icon_copy;
+ GpStatus stat;
ICONINFO iinfo;
- PICTDESC desc;
+ BITMAP bm;
+ int ret;
+ UINT width, height;
+ GpRect rect;
+ BitmapData lockeddata;
+ HDC screendc;
+ BOOL has_alpha;
+ int x, y;
+ BYTE *bits;
+ BITMAPINFOHEADER bih;
+ DWORD *src;
+ BYTE *dst_row;
+ DWORD *dst;
TRACE("%p, %p\n", hicon, bitmap);
if(!bitmap || !GetIconInfo(hicon, &iinfo))
+ {
+ DeleteObject(iinfo.hbmColor);
+ DeleteObject(iinfo.hbmMask);
return InvalidParameter;
+ }
- *bitmap = GdipAlloc(sizeof(GpBitmap));
- if(!*bitmap) return OutOfMemory;
+ /* get the size of the icon */
+ ret = GetObjectA(iinfo.hbmColor ? iinfo.hbmColor : iinfo.hbmMask, sizeof(bm), &bm);
+ if (ret == 0) {
+ DeleteObject(iinfo.hbmColor);
+ DeleteObject(iinfo.hbmMask);
+ return GenericError;
+ }
- icon_copy = CreateIconIndirect(&iinfo);
+ width = bm.bmWidth;
- if(!icon_copy){
- GdipFree(*bitmap);
- return InvalidParameter;
+ if (iinfo.hbmColor)
+ 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;
}
- desc.cbSizeofstruct = sizeof(PICTDESC);
- desc.picType = PICTYPE_ICON;
- desc.u.icon.hicon = icon_copy;
+ stat = GdipCreateBitmapFromScan0(width, height, 0, PixelFormat32bppARGB, NULL, bitmap);
+ if (stat != Ok) {
+ DeleteObject(iinfo.hbmColor);
+ DeleteObject(iinfo.hbmMask);
+ HeapFree(GetProcessHeap(), 0, bits);
+ return stat;
+ }
- if(OleCreatePictureIndirect(&desc, &IID_IPicture, TRUE,
- (LPVOID*) &((*bitmap)->image.picture)) != S_OK){
- DestroyIcon(icon_copy);
- GdipFree(*bitmap);
- return GenericError;
+ rect.X = 0;
+ rect.Y = 0;
+ rect.Width = width;
+ rect.Height = height;
+
+ stat = GdipBitmapLockBits(*bitmap, &rect, ImageLockModeWrite, PixelFormat32bppARGB, &lockeddata);
+ if (stat != Ok) {
+ DeleteObject(iinfo.hbmColor);
+ DeleteObject(iinfo.hbmMask);
+ HeapFree(GetProcessHeap(), 0, bits);
+ GdipDisposeImage((GpImage*)*bitmap);
+ return stat;
}
- (*bitmap)->format = PixelFormat32bppARGB;
- (*bitmap)->image.type = ImageTypeBitmap;
- (*bitmap)->image.flags = ImageFlagsNone;
- (*bitmap)->width = ipicture_pixel_width((*bitmap)->image.picture);
- (*bitmap)->height = ipicture_pixel_height((*bitmap)->image.picture);
- (*bitmap)->hbitmap = NULL;
- (*bitmap)->hdc = NULL;
- (*bitmap)->bits = NULL;
+ bih.biSize = sizeof(bih);
+ bih.biWidth = width;
+ bih.biHeight = -height;
+ bih.biPlanes = 1;
+ bih.biBitCount = 32;
+ bih.biCompression = BI_RGB;
+ bih.biSizeImage = 0;
+ bih.biXPelsPerMeter = 0;
+ bih.biYPelsPerMeter = 0;
+ bih.biClrUsed = 0;
+ bih.biClrImportant = 0;
+
+ screendc = GetDC(0);
+ if (iinfo.hbmColor)
+ {
+ GetDIBits(screendc, iinfo.hbmColor, 0, height, bits, (BITMAPINFO*)&bih, DIB_RGB_COLORS);
+
+ if (bm.bmBitsPixel == 32)
+ {
+ has_alpha = FALSE;
+
+ /* If any pixel has a non-zero alpha, ignore hbmMask */
+ src = (DWORD*)bits;
+ for (x=0; x<width && !has_alpha; x++)
+ for (y=0; y<height && !has_alpha; y++)
+ if ((*src++ & 0xff000000) != 0)
+ has_alpha = TRUE;
+ }
+ else has_alpha = FALSE;
+ }
+ else
+ {
+ GetDIBits(screendc, iinfo.hbmMask, 0, height, bits, (BITMAPINFO*)&bih, DIB_RGB_COLORS);
+ 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 (iinfo.hbmMask)
+ {
+ /* read alpha data from the mask */
+ if (iinfo.hbmColor)
+ GetDIBits(screendc, iinfo.hbmMask, 0, height, bits, (BITMAPINFO*)&bih, DIB_RGB_COLORS);
+ else
+ GetDIBits(screendc, iinfo.hbmMask, height, height, bits, (BITMAPINFO*)&bih, DIB_RGB_COLORS);
+
+ src = (DWORD*)bits;
+ dst_row = lockeddata.Scan0;
+ for (y=0; y<height; y++)
+ {
+ dst = (DWORD*)dst_row;
+ for (x=0; x<height; x++)
+ {
+ DWORD src_value = *src++;
+ if (src_value)
+ *dst++ = 0;
+ else
+ *dst++ |= 0xff000000;
+ }
+ dst_row += lockeddata.Stride;
+ }
+ }
+ else
+ {
+ /* set constant alpha of 255 */
+ dst_row = bits;
+ for (y=0; y<height; y++)
+ {
+ dst = (DWORD*)dst_row;
+ for (x=0; x<height; x++)
+ *dst++ |= 0xff000000;
+ dst_row += lockeddata.Stride;
+ }
+ }
+ }
+
+ ReleaseDC(0, screendc);
DeleteObject(iinfo.hbmColor);
DeleteObject(iinfo.hbmMask);
+ GdipBitmapUnlockBits(*bitmap, &lockeddata);
+
+ HeapFree(GetProcessHeap(), 0, bits);
+
return Ok;
}
More information about the wine-cvs
mailing list