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