diff --git a/PInvoke/Gdi32/GdiObjExtensions.cs b/PInvoke/Gdi32/GdiObjExtensions.cs
index ffeaaba8..133631cd 100644
--- a/PInvoke/Gdi32/GdiObjExtensions.cs
+++ b/PInvoke/Gdi32/GdiObjExtensions.cs
@@ -1,6 +1,7 @@
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
+using System.Runtime.InteropServices;
using Vanara.Extensions;
using Vanara.InteropServices;
using static Vanara.PInvoke.Gdi32;
@@ -54,6 +55,26 @@ namespace Vanara.PInvoke
}
}
+ /// Determines whether the bitmap is a bottom-up DIB.
+ /// The handle of the bitmap to assess.
+ /// if the specified bitmap is a bottom-up DIB; otherwise, .
+ public static bool IsBottomUpDIB(this in HBITMAP hbmp)
+ {
+ var dibSz = Marshal.SizeOf(typeof(DIBSECTION));
+ using var mem = GetObject(hbmp, dibSz);
+ return mem.Size == dibSz && mem.ToStructure().dsBmih.biHeight > 0;
+ }
+
+ /// Determines whether the bitmap is a bottom-up DIB.
+ /// The handle of the bitmap to assess.
+ /// if the specified bitmap is a bottom-up DIB; otherwise, .
+ public static bool IsDIB(this in HBITMAP hbmp)
+ {
+ var dibSz = Marshal.SizeOf(typeof(DIBSECTION));
+ using var mem = GetObject(hbmp, dibSz);
+ return mem.Size == dibSz;
+ }
+
/// Creates a from an preserving transparency, if possible.
/// The HBITMAP value.
/// The Bitmap instance. If is a NULL handle, is returned.
@@ -63,37 +84,27 @@ namespace Vanara.PInvoke
if (hbmp.IsNull) return null;
try
{
- var dibsection = GetObject(hbmp);
+ var dib = GetObject(hbmp);
+
// If hbmp doesn't have ARGB, then just use Gdi+
- if (dibsection.dsBm.bmBitsPixel != 32) return Image.FromHbitmap((IntPtr)hbmp);
- // Create resulting bitmap of same size with transparency and lock in memory
- var bitmap = new Bitmap(dibsection.dsBm.bmWidth, dibsection.dsBm.bmHeight, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
- var bmpData = bitmap.LockBits(new Rectangle(Point.Empty, bitmap.Size), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
- // Grab arrays to both DIB and result
- using var mstr = new SafeNativeArray(dibsection.dsBm.bmBits, (int)dibsection.dsBmih.biSizeImage, false);
- using var bstr = new SafeNativeArray(bmpData.Scan0, (int)dibsection.dsBmih.biSizeImage, false);
- // Copy all semi-transparent bits
- for (int i = 0; i < mstr.Count; i++)
- {
- var rgbquad = mstr[i];
- // If pixel is 100% transparent, skip pixel
- if (rgbquad.rgbReserved != 0)
- bstr[i] = rgbquad;
- }
- bitmap.UnlockBits(bmpData);
+ if (dib.dsBm.bmBitsPixel != 32) throw new Exception();
+
+ // Create resulting bitmap from DIB info
+ var bitmap = new Bitmap(dib.dsBmih.biWidth, dib.dsBmih.biHeight, dib.dsBm.bmWidthBytes, System.Drawing.Imaging.PixelFormat.Format32bppArgb, dib.dsBm.bmBits);
+
+ // Hack to determine and fix if upside-down
+ //var lkBits = bitmap.LockBits(new System.Drawing.Rectangle(Point.Empty, bitmap.Size), System.Drawing.Imaging.ImageLockMode.ReadWrite, bitmap.PixelFormat);
+ //var stride = lkBits.Stride;
+ //bitmap.UnlockBits(lkBits);
+ //if (stride > 0)
+ // bitmap.RotateFlip(RotateFlipType.Rotate180FlipNone);
+
return bitmap;
}
- catch
- {
- return Image.FromHbitmap((IntPtr)hbmp);
- }
+ catch { }
+ return Image.FromHbitmap((IntPtr)hbmp);
}
- /// Creates a from an preserving transparency, if possible.
- /// The SafeHBITMAP value.
- /// The Bitmap instance. If is a NULL handle, is returned.
- public static Bitmap ToBitmap(this SafeHBITMAP hbmp) => ((HBITMAP)hbmp).ToBitmap();
-
#if !NET20 && !NETSTANDARD2_0 && !NETCOREAPP2_0 && !NETCOREAPP2_1
/// Creates a from an preserving transparency, if possible.
/// The HBITMAP value.