1+ using SharpEmf . WmfTypes . Bitmap ;
2+ using SkiaSharp ;
3+
4+ namespace SharpEmf . Svg ;
5+
6+ internal static class BitmapUtils
7+ {
8+ public static unsafe string DibToPngBase64 ( byte [ ] dibData , BitmapInfoHeader bitmapHeader )
9+ {
10+ // TODO: this assumes that the DIB is 24-bit RGB, handle other cases
11+
12+ using var bitmap = new SKBitmap ( ) ;
13+
14+ var width = bitmapHeader . Width ;
15+ var height = bitmapHeader . Height ;
16+
17+ var rgbaData = DibToRgba ( dibData , bitmapHeader ) ;
18+
19+ fixed( byte * rgbaDataPtr = rgbaData )
20+ {
21+ var rgbaDataPtr2 = ( IntPtr ) rgbaDataPtr ;
22+ bitmap . InstallPixels ( new SKImageInfo ( width , height , SKColorType . Rgba8888 , SKAlphaType . Unpremul ) , rgbaDataPtr2 , width * 4 ) ;
23+ }
24+
25+ using var pngData = bitmap . Encode ( SKEncodedImageFormat . Png , 100 ) ;
26+ var resultBase64Str = Convert . ToBase64String ( pngData . Span ) ;
27+
28+ return resultBase64Str ;
29+ }
30+
31+ public static unsafe byte [ ] DibToRgba ( byte [ ] dibData , BitmapInfoHeader bitmapHeader )
32+ {
33+ var usedBytes = ( ushort ) bitmapHeader . BitCount / 8 * bitmapHeader . Width ;
34+ // DIB data is padded to the nearest DWORD (4-byte) boundary
35+ var padding = RoundUpToNearestMultipleOf4 ( usedBytes ) - usedBytes ;
36+
37+ var rgbaStride = bitmapHeader . Width * 4 ;
38+
39+ byte [ ] rgbaData = new byte [ rgbaStride * bitmapHeader . Height ] ;
40+
41+ fixed ( byte * dibDataPtr = dibData )
42+ {
43+ fixed ( byte * rgbaDataPtr = rgbaData )
44+ {
45+ var dibDataPtr2 = dibDataPtr ;
46+ var rgbaDataPtr2 = rgbaDataPtr ;
47+
48+ for ( int y = 0 ; y < bitmapHeader . Height ; y ++ )
49+ {
50+ // Due to the fact that emf arrays after reading are reversed, padding skipping is done before the X-row loop
51+ // Bytes order in EMF file: B, G, R, PADDED, PADDED, B, G, R, PADDED, PADDED, ...
52+ // After reversing: PADDED, PADDED, R, G, B, PADDED, PADDED, R, G, B, ...
53+ dibDataPtr2 += padding ;
54+
55+ for ( int x = 0 ; x < bitmapHeader . Width ; x ++ )
56+ {
57+ var r = * dibDataPtr2 ;
58+ var g = * ( dibDataPtr2 + 1 ) ;
59+ var b = * ( dibDataPtr2 + 2 ) ;
60+ const byte a = 0xFF ;
61+
62+ * rgbaDataPtr2 = r ;
63+ * ( rgbaDataPtr2 + 1 ) = g;
64+ * ( rgbaDataPtr2 + 2 ) = b;
65+ * ( rgbaDataPtr2 + 3 ) = a;
66+
67+ dibDataPtr2 += 3 ;
68+ rgbaDataPtr2 += 4 ;
69+ }
70+ }
71+ }
72+ }
73+
74+ return rgbaData ;
75+ }
76+
77+ private static int RoundUpToNearestMultipleOf4 ( int num )
78+ {
79+ return ( num + 3 ) / 4 * 4 ;
80+ }
81+ }
0 commit comments