@@ -20,6 +20,32 @@ public static partial class WindowsStorableHelpers
2020 private static ( Guid Format , Guid Encorder ) [ ] ? GdiEncoders ;
2121 private static ConcurrentDictionary < ( string , int , int ) , byte [ ] > ? DllIconCache ;
2222
23+ private const int PixelFormat32bppARGB = 2498570 ; // Added constant for transparency
24+
25+ [ StructLayout ( LayoutKind . Sequential ) ]
26+ private struct BITMAP // Added BITMAP structure for bitmap operations
27+ {
28+ public int bmType ;
29+ public int bmWidth ;
30+ public int bmHeight ;
31+ public int bmWidthBytes ;
32+ public ushort bmPlanes ;
33+ public ushort bmBitsPixel ;
34+ public IntPtr bmBits ;
35+ }
36+
37+ [ DllImport ( "gdi32.dll" , SetLastError = true ) ] // Added P/Invoke for GetObject
38+ private static extern int GetObject ( IntPtr hObject , int nCount , ref BITMAP lpObject ) ;
39+
40+ [ DllImport ( "gdiplus.dll" , SetLastError = true ) ] // Added P/Invoke for GdipCreateBitmapFromScan0
41+ private static extern int GdipCreateBitmapFromScan0 (
42+ int width ,
43+ int height ,
44+ int stride ,
45+ int pixelFormat ,
46+ IntPtr scan0 ,
47+ out IntPtr bitmap ) ;
48+
2349 // Methods
2450
2551 /// <inheritdoc cref="TryGetThumbnail"/>
@@ -57,15 +83,43 @@ public unsafe static HRESULT TryGetThumbnail(this IWindowsStorable storable, int
5783 return hr ;
5884 }
5985
60- // Convert to GpBitmap of GDI+
61- GpBitmap * gpBitmap = default ;
62- if ( PInvoke . GdipCreateBitmapFromHBITMAP ( hBitmap , HPALETTE . Null , & gpBitmap ) is not Status . Ok )
86+ // Retrieve BITMAP data
87+ BITMAP bmp = new BITMAP ( ) ;
88+ if ( GetObject ( ( nint ) hBitmap . Value , Marshal . SizeOf ( typeof ( BITMAP ) ) , ref bmp ) == 0 )
6389 {
64- if ( gpBitmap is not null ) PInvoke . GdipDisposeImage ( ( GpImage * ) gpBitmap ) ;
6590 if ( ! hBitmap . IsNull ) PInvoke . DeleteObject ( hBitmap ) ;
6691 return HRESULT . E_FAIL ;
6792 }
6893
94+ // Allocate buffer for flipped pixel data
95+ IntPtr flippedBits = Marshal . AllocHGlobal ( bmp . bmWidthBytes * bmp . bmHeight ) ;
96+ byte * src = ( byte * ) bmp . bmBits ;
97+ byte * dst = ( byte * ) flippedBits ;
98+
99+ // Flip the image manually row by row
100+ for ( int y = 0 ; y < bmp . bmHeight ; y ++ )
101+ {
102+ Buffer . MemoryCopy (
103+ src + y * bmp . bmWidthBytes ,
104+ dst + ( bmp . bmHeight - y - 1 ) * bmp . bmWidthBytes ,
105+ bmp . bmWidthBytes ,
106+ bmp . bmWidthBytes
107+ ) ;
108+ }
109+
110+ // Create GpBitmap from the flipped pixel data
111+ IntPtr gpBitmapPtr ;
112+ if ( GdipCreateBitmapFromScan0 ( bmp . bmWidth , bmp . bmHeight , bmp . bmWidthBytes , PixelFormat32bppARGB , flippedBits , out gpBitmapPtr ) != 0 )
113+ {
114+ Marshal . FreeHGlobal ( flippedBits ) ;
115+ if ( ! hBitmap . IsNull ) PInvoke . DeleteObject ( hBitmap ) ;
116+ return HRESULT . E_FAIL ;
117+ }
118+
119+ Marshal . FreeHGlobal ( flippedBits ) ;
120+
121+ GpBitmap * gpBitmap = ( GpBitmap * ) gpBitmapPtr ;
122+
69123 if ( TryConvertGpBitmapToByteArray ( gpBitmap , out thumbnailData ) )
70124 {
71125 if ( ! hBitmap . IsNull ) PInvoke . DeleteObject ( hBitmap ) ;
0 commit comments