コード例 #1
0
        private unsafe Bitmap BmpFrame()
        {
            Bitmap?bitmap = null;

            if (_iconData != null && _bestBitDepth == 32)
            {
                // GDI+ doesnt handle 32 bpp icons with alpha properly
                // we load the icon ourself from the byte table
                bitmap = new Bitmap(Size.Width, Size.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
                Debug.Assert(_bestImageOffset >= 0 && (_bestImageOffset + _bestBytesInRes) <= _iconData.Length, "Illegal offset/length for the Icon data");

                unsafe
                {
                    BitmapData bmpdata = bitmap.LockBits(new Rectangle(0, 0, Size.Width, Size.Height),
                                                         ImageLockMode.WriteOnly,
                                                         PixelFormat.Format32bppArgb);
                    try
                    {
                        uint *pixelPtr = (uint *)bmpdata.Scan0.ToPointer();

                        // jumping the image header
                        int newOffset = (int)(_bestImageOffset + sizeof(NativeMethods.BITMAPINFOHEADER));
                        // there is no color table that we need to skip since we're 32bpp

                        int lineLength = Size.Width * 4;
                        int width      = Size.Width;
                        for (int j = (Size.Height - 1) * 4; j >= 0; j -= 4)
                        {
                            Marshal.Copy(_iconData, newOffset + j * width, (IntPtr)pixelPtr, lineLength);
                            pixelPtr += width;
                        }

                        // note: we ignore the mask that's available after the pixel table
                    }
                    finally
                    {
                        bitmap.UnlockBits(bmpdata);
                    }
                }
            }
            else if (_bestBitDepth == 0 || _bestBitDepth == 32)
            {
                // This may be a 32bpp icon or an icon without any data.
                SafeNativeMethods.ICONINFO info = default;
                SafeNativeMethods.GetIconInfo(new HandleRef(this, _handle), ref info);
                SafeNativeMethods.BITMAP bmp = default;
                try
                {
                    if (info.hbmColor != IntPtr.Zero)
                    {
                        SafeNativeMethods.GetObject(new HandleRef(null, info.hbmColor), sizeof(SafeNativeMethods.BITMAP), ref bmp);
                        if (bmp.bmBitsPixel == 32)
                        {
                            Bitmap?    tmpBitmap  = null;
                            BitmapData?bmpData    = null;
                            BitmapData?targetData = null;
                            try
                            {
                                tmpBitmap = Image.FromHbitmap(info.hbmColor);

                                // In GDI+ the bits are there but the bitmap was created with no alpha channel
                                // so copy the bits by hand to a new bitmap
                                // we also need to go around a limitation in the way the ICON is stored (ie if it's another bpp
                                // but stored in 32bpp all pixels are transparent and not opaque)
                                // (Here you mostly need to remain calm....)
                                bmpData = tmpBitmap.LockBits(new Rectangle(0, 0, tmpBitmap.Width, tmpBitmap.Height), ImageLockMode.ReadOnly, tmpBitmap.PixelFormat);

                                // we need do the following if the image has alpha because otherwise the image is fully transparent even though it has data
                                if (BitmapHasAlpha(bmpData))
                                {
                                    bitmap     = new Bitmap(bmpData.Width, bmpData.Height, PixelFormat.Format32bppArgb);
                                    targetData = bitmap.LockBits(new Rectangle(0, 0, bmpData.Width, bmpData.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);

                                    CopyBitmapData(bmpData, targetData);
                                }
                            }
                            finally
                            {
                                if (tmpBitmap != null && bmpData != null)
                                {
                                    tmpBitmap.UnlockBits(bmpData);
                                }
                                if (bitmap != null && targetData != null)
                                {
                                    bitmap.UnlockBits(targetData);
                                }
                            }
                            tmpBitmap.Dispose();
                        }
                    }
                }
                finally
                {
                    if (info.hbmColor != IntPtr.Zero)
                    {
                        Interop.Gdi32.DeleteObject(info.hbmColor);
                    }
                    if (info.hbmMask != IntPtr.Zero)
                    {
                        Interop.Gdi32.DeleteObject(info.hbmMask);
                    }
                }
            }


            if (bitmap == null)
            {
                // last chance... all the other cases (ie non 32 bpp icons coming from a handle or from the bitmapData)

                // we have to do this rather than just return Bitmap.FromHIcon because
                // the bitmap returned from that, even though it's 32bpp, just paints where the mask allows it
                // seems like another GDI+ weirdness. might be interesting to investigate further. In the meantime
                // this looks like the right thing to do and is not more expansive that what was present before.

                Size size = Size;
                bitmap = new Bitmap(size.Width, size.Height); // initialized to transparent
                Graphics?graphics = null;
                using (graphics = Graphics.FromImage(bitmap))
                {
                    try
                    {
                        using (Bitmap tmpBitmap = Bitmap.FromHicon(Handle))
                        {
                            graphics.DrawImage(tmpBitmap, new Rectangle(0, 0, size.Width, size.Height));
                        }
                    }
                    catch (ArgumentException)
                    {
                        // Sometimes FromHicon will crash with no real reason.
                        // The backup plan is to just draw the image like we used to.
                        // NOTE: FromHIcon is also where we have the buffer overrun
                        // if width and height are mismatched.
                        Draw(graphics, new Rectangle(0, 0, size.Width, size.Height));
                    }
                }


                // GDI+ fills the surface with a sentinel color for GetDC, but does
                // not correctly clean it up again, so we have to do it.
                Color fakeTransparencyColor = Color.FromArgb(0x0d, 0x0b, 0x0c);
                bitmap.MakeTransparent(fakeTransparencyColor);
            }

            Debug.Assert(bitmap != null, "Bitmap cannot be null");
            return(bitmap);
        }
コード例 #2
0
 public unsafe Bitmap ToBitmap()
 {
     Bitmap image = null;
     if ((this.iconData != null) && (this.bestBitDepth == 0x20))
     {
         image = new Bitmap(this.Size.Width, this.Size.Height, PixelFormat.Format32bppArgb);
         BitmapData bitmapdata = image.LockBits(new Rectangle(0, 0, this.Size.Width, this.Size.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
         try
         {
             uint* numPtr = (uint*) bitmapdata.Scan0.ToPointer();
             int num = this.bestImageOffset + Marshal.SizeOf(typeof(SafeNativeMethods.BITMAPINFOHEADER));
             int length = this.Size.Width * 4;
             int width = this.Size.Width;
             for (int i = (this.Size.Height - 1) * 4; i >= 0; i -= 4)
             {
                 Marshal.Copy(this.iconData, num + (i * width), (IntPtr) numPtr, length);
                 numPtr += width;
             }
         }
         finally
         {
             image.UnlockBits(bitmapdata);
         }
     }
     else if ((this.bestBitDepth == 0) || (this.bestBitDepth == 0x20))
     {
         SafeNativeMethods.ICONINFO info = new SafeNativeMethods.ICONINFO();
         SafeNativeMethods.GetIconInfo(new HandleRef(this, this.handle), info);
         SafeNativeMethods.BITMAP bm = new SafeNativeMethods.BITMAP();
         try
         {
             if (info.hbmColor != IntPtr.Zero)
             {
                 SafeNativeMethods.GetObject(new HandleRef(null, info.hbmColor), Marshal.SizeOf(typeof(SafeNativeMethods.BITMAP)), bm);
                 if (bm.bmBitsPixel == 0x20)
                 {
                     Bitmap bitmap3 = null;
                     BitmapData bmpData = null;
                     BitmapData targetData = null;
                     System.Drawing.IntSecurity.ObjectFromWin32Handle.Assert();
                     try
                     {
                         bitmap3 = Image.FromHbitmap(info.hbmColor);
                         bmpData = bitmap3.LockBits(new Rectangle(0, 0, bitmap3.Width, bitmap3.Height), ImageLockMode.ReadOnly, bitmap3.PixelFormat);
                         if (BitmapHasAlpha(bmpData))
                         {
                             image = new Bitmap(bmpData.Width, bmpData.Height, PixelFormat.Format32bppArgb);
                             targetData = image.LockBits(new Rectangle(0, 0, bmpData.Width, bmpData.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
                             this.CopyBitmapData(bmpData, targetData);
                         }
                     }
                     finally
                     {
                         CodeAccessPermission.RevertAssert();
                         if ((bitmap3 != null) && (bmpData != null))
                         {
                             bitmap3.UnlockBits(bmpData);
                         }
                         if ((image != null) && (targetData != null))
                         {
                             image.UnlockBits(targetData);
                         }
                     }
                     bitmap3.Dispose();
                 }
             }
         }
         finally
         {
             if (info.hbmColor != IntPtr.Zero)
             {
                 SafeNativeMethods.IntDeleteObject(new HandleRef(null, info.hbmColor));
             }
             if (info.hbmMask != IntPtr.Zero)
             {
                 SafeNativeMethods.IntDeleteObject(new HandleRef(null, info.hbmMask));
             }
         }
     }
     if (image == null)
     {
         System.Drawing.Size size = this.Size;
         image = new Bitmap(size.Width, size.Height);
         using (Graphics graphics = null)
         {
             graphics = Graphics.FromImage(image);
             System.Drawing.IntSecurity.ObjectFromWin32Handle.Assert();
             try
             {
                 using (Bitmap bitmap4 = Bitmap.FromHicon(this.Handle))
                 {
                     graphics.DrawImage(bitmap4, new Rectangle(0, 0, size.Width, size.Height));
                 }
             }
             catch (ArgumentException)
             {
                 this.Draw(graphics, new Rectangle(0, 0, size.Width, size.Height));
             }
             finally
             {
                 CodeAccessPermission.RevertAssert();
             }
         }
         Color transparentColor = Color.FromArgb(13, 11, 12);
         image.MakeTransparent(transparentColor);
     }
     return image;
 }
コード例 #3
0
ファイル: Icon.cs プロジェクト: JianwenSun/cc
        public Bitmap ToBitmap() {
            Bitmap bitmap = null;
            if(iconData != null && bestBitDepth == 32) {
                // GDI+ doesnt handle 32 bpp icons with alpha properly
                // we load the icon ourself from the byte table
                bitmap = new Bitmap(Size.Width, Size.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
                Debug.Assert(bestImageOffset >= 0 && (bestImageOffset + 40 + (Size.Width * Size.Height - 1)*4) <= iconData.Length, "Illegal offset/length for the Icon data");

                unsafe
                {
                    System.Drawing.Imaging.BitmapData bmpdata = bitmap.LockBits(new Rectangle(0, 0, Size.Width, Size.Height), 
                        System.Drawing.Imaging.ImageLockMode.WriteOnly, 
                        System.Drawing.Imaging.PixelFormat.Format32bppArgb);
                    try
                    {
                        uint * pixelPtr = (uint*)bmpdata.Scan0.ToPointer();

                        // jumping the image header
                        int newOffset = bestImageOffset + Marshal.SizeOf(typeof(SafeNativeMethods.BITMAPINFOHEADER));
                        // there is no color table that we need to skip since we're 32bpp
                        
                        int lineLength = Size.Width * 4;
                        int width = Size.Width;
                        for(int j=(Size.Height-1)*4;j>=0;j-=4) 
                        {
                            Marshal.Copy(iconData, newOffset + j * width, (IntPtr)pixelPtr, lineLength);
                            pixelPtr+=width;
                        }

                        // note: we ignore the mask that's available after the pixel table
                    }
                    finally
                    {
                        bitmap.UnlockBits(bmpdata);
                    }
                }
            } else if(bestBitDepth == 0 || bestBitDepth == 32){ // we don't know or we are 32bpp for sure
                //we don't have any icon data, let's fish out the data from the handle that we got...
                // we have to fish out the data for this icon if the icon is a 32bpp icon
                SafeNativeMethods.ICONINFO info = new SafeNativeMethods.ICONINFO();
                SafeNativeMethods.GetIconInfo(new HandleRef(this, handle), info);
                SafeNativeMethods.BITMAP bmp = new SafeNativeMethods.BITMAP();
                try {
                    if (info.hbmColor != IntPtr.Zero) {
                        SafeNativeMethods.GetObject(new HandleRef(null, info.hbmColor), Marshal.SizeOf(typeof(SafeNativeMethods.BITMAP)), bmp);
                        if(bmp.bmBitsPixel ==32) {
                            Bitmap tmpBitmap = null;
                            BitmapData bmpData = null;
                            BitmapData targetData = null;
                            // SECREVIEW : This assert is safe here, all data passed to unmanaged code is created by us.  The scope is ok too,
                            //             most operations in it demand this permission.
                            //
                            IntSecurity.ObjectFromWin32Handle.Assert();
                            try
                            {
                                tmpBitmap = Bitmap.FromHbitmap(info.hbmColor);

                                // 




                                bmpData = tmpBitmap.LockBits(new Rectangle(0,0, tmpBitmap.Width, tmpBitmap.Height), ImageLockMode.ReadOnly, tmpBitmap.PixelFormat);

                                // we need do the following if the image has alpha because otherwise the image is fully transparent even though it has data
                                if(BitmapHasAlpha(bmpData)) {
                                    bitmap = new Bitmap(bmpData.Width, bmpData.Height, PixelFormat.Format32bppArgb);
                                    targetData = bitmap.LockBits(new Rectangle(0, 0, bmpData.Width, bmpData.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);

                                    // SECREVIEW : both bmpData and targetData point to memory owned by this Icon object so the following call
                                    //             is safe.
                                    //
                                    CopyBitmapData(bmpData, targetData);
                                }
                            } finally {
                                CodeAccessPermission.RevertAssert();
                                if(tmpBitmap != null && bmpData != null) {
                                    tmpBitmap.UnlockBits(bmpData);
                                }
                                if(bitmap != null && targetData != null) {
                                    bitmap.UnlockBits(targetData);
                                }
                            }
                            tmpBitmap.Dispose();
                        }
                    }
                } finally {
                    if(info.hbmColor != IntPtr.Zero)
                        SafeNativeMethods.IntDeleteObject(new HandleRef(null, info.hbmColor));
                    if(info.hbmMask != IntPtr.Zero) 
                        SafeNativeMethods.IntDeleteObject(new HandleRef(null, info.hbmMask));
                }
            }


            if(bitmap == null) {                
                // last chance... all the other cases (ie non 32 bpp icons coming from a handle or from the bitmapData)

                // we have to do this rather than just return Bitmap.FromHIcon because 
                // the bitmap returned from that, even though it's 32bpp, just paints where the mask allows it
                // seems like another GDI+ weirdness. might be interesting to investigate further. In the meantime
                // this looks like the right thing to do and is not more expansive that what was present before.
                
                Size size = Size;
                bitmap = new Bitmap(size.Width, size.Height); // initialized to transparent
                Graphics graphics = null;
                try {
                    graphics = Graphics.FromImage(bitmap);
                    // SECREVIEW : This assert is safe here, no user data is involved here.
                    //
                    IntSecurity.ObjectFromWin32Handle.Assert();
                    try{
                        using(Bitmap tmpBitmap = Bitmap.FromHicon(this.Handle)) {
                            graphics.DrawImage(tmpBitmap, new Rectangle(0, 0, size.Width, size.Height));
                        }
                    } catch(ArgumentException) { // GDI+ weirdness episode MMMCLXXXXIVI, sometime FromHicon crash with no real reason,
                        // see VSWhidbey 518812
                        // backup plan is to just draw the image like we used to. 
                        // NOTE: FromHIcon is also where we have the buffer overrun
                        // if width and height are mismatched
                        Draw(graphics, new Rectangle(0, 0, size.Width, size.Height));
                    }
                    finally{
                        CodeAccessPermission.RevertAssert();
                    }
                }
                finally {
                    if (graphics != null) {
                        graphics.Dispose();
                    }
                }

                
                // gpr: GDI+ is filling the surface with a sentinel color for GetDC,
                // but is not correctly cleaning it up again, so we have to for it.
                Color fakeTransparencyColor = Color.FromArgb(0x0d, 0x0b, 0x0c);
                bitmap.MakeTransparent(fakeTransparencyColor);
                
            }                
            
            Debug.Assert(bitmap != null, "Bitmap cannot be null");
            return bitmap;
            
        }
コード例 #4
0
        public unsafe Bitmap ToBitmap()
        {
            Bitmap image = null;

            if ((this.iconData != null) && (this.bestBitDepth == 0x20))
            {
                image = new Bitmap(this.Size.Width, this.Size.Height, PixelFormat.Format32bppArgb);
                BitmapData bitmapdata = image.LockBits(new Rectangle(0, 0, this.Size.Width, this.Size.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
                try
                {
                    uint *numPtr = (uint *)bitmapdata.Scan0.ToPointer();
                    int   num    = this.bestImageOffset + Marshal.SizeOf(typeof(SafeNativeMethods.BITMAPINFOHEADER));
                    int   length = this.Size.Width * 4;
                    int   width  = this.Size.Width;
                    for (int i = (this.Size.Height - 1) * 4; i >= 0; i -= 4)
                    {
                        Marshal.Copy(this.iconData, num + (i * width), (IntPtr)numPtr, length);
                        numPtr += width;
                    }
                }
                finally
                {
                    image.UnlockBits(bitmapdata);
                }
            }
            else if ((this.bestBitDepth == 0) || (this.bestBitDepth == 0x20))
            {
                SafeNativeMethods.ICONINFO info = new SafeNativeMethods.ICONINFO();
                SafeNativeMethods.GetIconInfo(new HandleRef(this, this.handle), info);
                SafeNativeMethods.BITMAP bm = new SafeNativeMethods.BITMAP();
                try
                {
                    if (info.hbmColor != IntPtr.Zero)
                    {
                        SafeNativeMethods.GetObject(new HandleRef(null, info.hbmColor), Marshal.SizeOf(typeof(SafeNativeMethods.BITMAP)), bm);
                        if (bm.bmBitsPixel == 0x20)
                        {
                            Bitmap     bitmap3    = null;
                            BitmapData bmpData    = null;
                            BitmapData targetData = null;
                            System.Drawing.IntSecurity.ObjectFromWin32Handle.Assert();
                            try
                            {
                                bitmap3 = Image.FromHbitmap(info.hbmColor);
                                bmpData = bitmap3.LockBits(new Rectangle(0, 0, bitmap3.Width, bitmap3.Height), ImageLockMode.ReadOnly, bitmap3.PixelFormat);
                                if (BitmapHasAlpha(bmpData))
                                {
                                    image      = new Bitmap(bmpData.Width, bmpData.Height, PixelFormat.Format32bppArgb);
                                    targetData = image.LockBits(new Rectangle(0, 0, bmpData.Width, bmpData.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
                                    this.CopyBitmapData(bmpData, targetData);
                                }
                            }
                            finally
                            {
                                CodeAccessPermission.RevertAssert();
                                if ((bitmap3 != null) && (bmpData != null))
                                {
                                    bitmap3.UnlockBits(bmpData);
                                }
                                if ((image != null) && (targetData != null))
                                {
                                    image.UnlockBits(targetData);
                                }
                            }
                            bitmap3.Dispose();
                        }
                    }
                }
                finally
                {
                    if (info.hbmColor != IntPtr.Zero)
                    {
                        SafeNativeMethods.IntDeleteObject(new HandleRef(null, info.hbmColor));
                    }
                    if (info.hbmMask != IntPtr.Zero)
                    {
                        SafeNativeMethods.IntDeleteObject(new HandleRef(null, info.hbmMask));
                    }
                }
            }
            if (image == null)
            {
                System.Drawing.Size size = this.Size;
                image = new Bitmap(size.Width, size.Height);
                using (Graphics graphics = null)
                {
                    graphics = Graphics.FromImage(image);
                    System.Drawing.IntSecurity.ObjectFromWin32Handle.Assert();
                    try
                    {
                        using (Bitmap bitmap4 = Bitmap.FromHicon(this.Handle))
                        {
                            graphics.DrawImage(bitmap4, new Rectangle(0, 0, size.Width, size.Height));
                        }
                    }
                    catch (ArgumentException)
                    {
                        this.Draw(graphics, new Rectangle(0, 0, size.Width, size.Height));
                    }
                    finally
                    {
                        CodeAccessPermission.RevertAssert();
                    }
                }
                Color transparentColor = Color.FromArgb(13, 11, 12);
                image.MakeTransparent(transparentColor);
            }
            return(image);
        }