From 2b55fe5755b0f78385c237beab3e255e07dbb7f3 Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Mon, 23 Mar 2020 15:53:35 -0700 Subject: [PATCH] More efficient interop for BITMAPINFOHEADER (#33967) --- .../Drawing/BufferedGraphicsContext.Windows.cs | 5 ++--- .../src/System/Drawing/Gdiplus.cs | 16 ---------------- .../src/System/Drawing/Icon.Unix.cs | 4 ++-- .../src/System/Drawing/Icon.Windows.cs | 2 +- .../src/System/Drawing/NativeMethods.cs | 13 ++++++------- 5 files changed, 11 insertions(+), 29 deletions(-) diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/BufferedGraphicsContext.Windows.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/BufferedGraphicsContext.Windows.cs index 97896f67a1a73..1eaaba5447c9a 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/BufferedGraphicsContext.Windows.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/BufferedGraphicsContext.Windows.cs @@ -89,7 +89,7 @@ private BufferedGraphics AllocBuffer(Graphics? targetGraphics, IntPtr targetDC, /// table or bitmasks, as appropriate. /// /// True if successful, false otherwise. - private bool FillBitmapInfo(IntPtr hdc, IntPtr hpal, ref NativeMethods.BITMAPINFO_FLAT pbmi) + private unsafe bool FillBitmapInfo(IntPtr hdc, IntPtr hpal, ref NativeMethods.BITMAPINFO_FLAT pbmi) { IntPtr hbm = IntPtr.Zero; bool bRet = false; @@ -104,8 +104,7 @@ private bool FillBitmapInfo(IntPtr hdc, IntPtr hpal, ref NativeMethods.BITMAPINF throw new OutOfMemoryException(SR.GraphicsBufferQueryFail); } - pbmi.bmiHeader_biSize = Marshal.SizeOf(typeof(NativeMethods.BITMAPINFOHEADER)); - pbmi.bmiColors = new byte[NativeMethods.BITMAPINFO_MAX_COLORSIZE * 4]; + pbmi.bmiHeader_biSize = sizeof(NativeMethods.BITMAPINFOHEADER); // Call first time to fill in BITMAPINFO header. SafeNativeMethods.GetDIBits(new HandleRef(null, hdc), diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/Gdiplus.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/Gdiplus.cs index 6fee50f351aa3..e42459df59d1b 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/Gdiplus.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/Gdiplus.cs @@ -562,22 +562,6 @@ public struct BITMAP public IntPtr bmBits; } - [StructLayout(LayoutKind.Sequential)] - public class BITMAPINFOHEADER - { - public int biSize = 40; - public int biWidth; - public int biHeight; - public short biPlanes; - public short biBitCount; - public int biCompression; - public int biSizeImage; - public int biXPelsPerMeter; - public int biYPelsPerMeter; - public int biClrUsed; - public int biClrImportant; - } - // https://devblogs.microsoft.com/oldnewthing/20101018-00/?p=12513 // https://devblogs.microsoft.com/oldnewthing/20120720-00/?p=7083 diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/Icon.Unix.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/Icon.Unix.cs index 62e345e1caca6..96c81dab0eded 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/Icon.Unix.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/Icon.Unix.cs @@ -449,7 +449,7 @@ private void SaveBestSingleIcon(BinaryWriter writer, int width, int height) SaveIconImage(writer, (IconImage)imageData![best]); } - private void SaveBitmapAsIcon(BinaryWriter writer) + private unsafe void SaveBitmapAsIcon(BinaryWriter writer) { writer.Write((ushort)0); // idReserved must be 0 writer.Write((ushort)1); // idType must be 1 @@ -466,7 +466,7 @@ private void SaveBitmapAsIcon(BinaryWriter writer) ide.imageOffset = 22; // 22 is the first icon position (for single icon files) BitmapInfoHeader bih = default; - bih.biSize = (uint)Marshal.SizeOf(typeof(BitmapInfoHeader)); + bih.biSize = (uint)sizeof(BitmapInfoHeader); bih.biWidth = bitmap.Width; bih.biHeight = 2 * bitmap.Height; // include both XOR and AND images bih.biPlanes = 1; diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/Icon.Windows.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/Icon.Windows.cs index ad699974c90f5..02021231f9f29 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/Icon.Windows.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/Icon.Windows.cs @@ -738,7 +738,7 @@ private unsafe Bitmap BmpFrame() uint* pixelPtr = (uint*)bmpdata.Scan0.ToPointer(); // jumping the image header - int newOffset = (int)(_bestImageOffset + Marshal.SizeOf(typeof(SafeNativeMethods.BITMAPINFOHEADER))); + 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; diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/NativeMethods.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/NativeMethods.cs index 5b12a5bdc5828..b317e652b968e 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/NativeMethods.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/NativeMethods.cs @@ -9,7 +9,7 @@ namespace System.Drawing { internal class NativeMethods { - internal static HandleRef NullHandleRef = new HandleRef(null, IntPtr.Zero); + internal static HandleRef NullHandleRef => new HandleRef(null, IntPtr.Zero); public const int MAX_PATH = 260; internal const int SM_REMOTESESSION = 0x1000; @@ -20,9 +20,9 @@ internal class NativeMethods internal const int BITMAPINFO_MAX_COLORSIZE = 256; [StructLayout(LayoutKind.Sequential)] - internal struct BITMAPINFO_FLAT + internal unsafe struct BITMAPINFO_FLAT { - public int bmiHeader_biSize; // = Marshal.SizeOf(typeof(BITMAPINFOHEADER)); + public int bmiHeader_biSize; // = sizeof(BITMAPINFOHEADER) public int bmiHeader_biWidth; public int bmiHeader_biHeight; public short bmiHeader_biPlanes; @@ -34,14 +34,13 @@ internal struct BITMAPINFO_FLAT public int bmiHeader_biClrUsed; public int bmiHeader_biClrImportant; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = BITMAPINFO_MAX_COLORSIZE * 4)] - public byte[] bmiColors; // RGBQUAD structs... Blue-Green-Red-Reserved, repeat... + public fixed byte bmiColors[BITMAPINFO_MAX_COLORSIZE * 4]; // RGBQUAD structs... Blue-Green-Red-Reserved, repeat... } [StructLayout(LayoutKind.Sequential)] - internal class BITMAPINFOHEADER + internal struct BITMAPINFOHEADER { - public int biSize = 40; + public int biSize; public int biWidth; public int biHeight; public short biPlanes;