From fc804655a69d59755735dc20f724d2ca3ef25b25 Mon Sep 17 00:00:00 2001 From: Carsten Schuette Date: Thu, 3 Feb 2022 08:43:27 +0100 Subject: [PATCH] Optimize DibHelper a bit, now only needs one byte array instead of two (#348) --- src/Greenshot.Base/Core/DibHelper.cs | 52 ++++++++++++++-------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/src/Greenshot.Base/Core/DibHelper.cs b/src/Greenshot.Base/Core/DibHelper.cs index 70708a0b5..bfe01b201 100644 --- a/src/Greenshot.Base/Core/DibHelper.cs +++ b/src/Greenshot.Base/Core/DibHelper.cs @@ -23,9 +23,12 @@ namespace Greenshot.Base.Core /// The image converted to DIB, in bytes. public static byte[] ConvertToDib(Image image) { - byte[] bm32bData; + byte[] fullImage; + int dataLength; int width = image.Width; int height = image.Height; + const int hdrSize = 0x28; + // Ensure image is 32bppARGB by painting it on a new 32bppARGB image. using (var bm32b = ImageHelper.CreateEmptyLike(image, Color.Transparent, PixelFormat.Format32bppArgb)) { @@ -33,26 +36,40 @@ namespace Greenshot.Base.Core { graphics.DrawImage(image, new Rectangle(0, 0, bm32b.Width, bm32b.Height)); } + // Bitmap format has its lines reversed. bm32b.RotateFlip(RotateFlipType.Rotate180FlipX); - bm32bData = GetImageData(bm32b, out var stride); - } - // BITMAPINFOHEADER struct for DIB. - uint hdrSize = 0x28; - var fullImage = new byte[hdrSize + 12 + bm32bData.Length]; - var bitmapInfoHeader = MemoryMarshal.Cast(fullImage.AsSpan()); + // Copy bitmap data into a new byte array with additional space for BITMAPINFOHEADER + BitmapData bm32bBitmapData = null; + try + { + bm32bBitmapData = bm32b.LockBits(new Rectangle(0, 0, bm32b.Width, bm32b.Height), ImageLockMode.ReadOnly, bm32b.PixelFormat); + dataLength = bm32bBitmapData.Stride * bm32b.Height; + fullImage = new byte[hdrSize + 12 + dataLength]; + Marshal.Copy(bm32bBitmapData.Scan0, fullImage, hdrSize + 12, dataLength); + } + finally + { + if (bm32bBitmapData != null) + { + bm32b.UnlockBits(bm32bBitmapData); + } + } + } + + // BITMAPINFOHEADER struct for DIB. + var bitmapInfoHeader = MemoryMarshal.Cast(fullImage.AsSpan()); bitmapInfoHeader[0].biSize = hdrSize; bitmapInfoHeader[0].biWidth = width; bitmapInfoHeader[0].biHeight = height; bitmapInfoHeader[0].biPlanes = 1; bitmapInfoHeader[0].biBitCount = 32; bitmapInfoHeader[0].biCompression = BI_COMPRESSION.BI_BITFIELDS; - bitmapInfoHeader[0].biSizeImage = (uint)bm32bData.Length; + bitmapInfoHeader[0].biSizeImage = (uint)dataLength; bitmapInfoHeader[0].biXPelsPerMeter = (int)(image.HorizontalResolution * 39.3701); bitmapInfoHeader[0].biYPelsPerMeter = (int)(image.VerticalResolution * 39.3701); - // The aforementioned "BITFIELDS": colour masks applied to the Int32 pixel value to get the R, G and B values. bitmapInfoHeader[0].bV5RedMask = 0x00FF0000; bitmapInfoHeader[0].bV5GreenMask = 0x0000FF00; @@ -62,24 +79,7 @@ namespace Greenshot.Base.Core //Int32 biClrUsed = 0; //Int32 biClrImportant = 0; - Array.Copy(bm32bData, 0, fullImage, hdrSize + 12, bm32bData.Length); return fullImage; } - - /// - /// Gets the raw bytes from an image. - /// - /// The image to get the bytes from. - /// Stride of the retrieved image data. - /// The raw bytes of the image - public static byte[] GetImageData(Bitmap sourceImage, out int stride) - { - BitmapData sourceData = sourceImage.LockBits(new Rectangle(0, 0, sourceImage.Width, sourceImage.Height), ImageLockMode.ReadOnly, sourceImage.PixelFormat); - stride = sourceData.Stride; - byte[] data = new byte[stride * sourceImage.Height]; - Marshal.Copy(sourceData.Scan0, data, 0, data.Length); - sourceImage.UnlockBits(sourceData); - return data; - } } }