@@ -10,6 +10,13 @@ namespace CodeCave.Revit.Toolkit.Thumbnails
10
10
/// </summary>
11
11
public class DwgThumbnailExtractor : ThumbnailExtractor
12
12
{
13
+ private static readonly Color ColorBlack = Color . Black ;
14
+
15
+ private static readonly Color ColorWhite = Color . White ;
16
+
17
+ private bool RetainBackgroudColor { get ; set ; } = true ;
18
+
19
+ /// <inheritdoc/>
13
20
public override byte [ ] ExtractThumbnailBytes ( Stream stream )
14
21
{
15
22
using var binaryReader = new BinaryReader ( stream ) ;
@@ -24,51 +31,102 @@ public override byte[] ExtractThumbnailBytes(Stream stream)
24
31
25
32
for ( short i = 1 ; i <= byteCount ; i ++ )
26
33
{
27
- var imageCode = binaryReader . ReadByte ( ) ;
28
- var imageHeaderStart = binaryReader . ReadInt32 ( ) ;
29
- var imageHeaderSize = binaryReader . ReadInt32 ( ) ;
34
+ var thumbInfo = new ThumbnailInfo
35
+ {
36
+ Type = binaryReader . ReadByte ( ) ,
37
+ Start = binaryReader . ReadInt32 ( ) ,
38
+ Length = binaryReader . ReadInt32 ( ) ,
39
+ } ;
30
40
31
41
#pragma warning disable CC0120 // default just skips to the next byte
32
- switch ( imageCode )
42
+ switch ( thumbInfo . Type )
33
43
{
34
44
// PNG thumbnail - ACAD 2013 and later
35
- case ThumbnailImageCodes . PNG :
45
+ case ThumbnailInfo . PngType :
36
46
var ms2013 = new MemoryStream ( ) ;
37
- stream . Seek ( imageHeaderStart , SeekOrigin . Begin ) ;
38
- stream . CopyTo ( ms2013 , imageHeaderSize ) ;
47
+ stream . Seek ( thumbInfo . Start , SeekOrigin . Begin ) ;
48
+ stream . CopyTo ( ms2013 , thumbInfo . Length ) ;
39
49
var byte2013 = ms2013 . ToArray ( ) ;
40
50
41
51
return byte2013 ;
42
52
43
53
// BMP Preview (2010 file format and lower)
44
- case ThumbnailImageCodes . BMP :
45
- binaryReader . ReadBytes ( 0xe ) ;
46
- var biBitCount = binaryReader . ReadUInt16 ( ) ;
47
- binaryReader . ReadBytes ( 4 ) ;
48
- var biSizeImage = binaryReader . ReadUInt32 ( ) ;
49
-
50
- stream . Seek ( imageHeaderStart , SeekOrigin . Begin ) ;
51
- var bitmapBuffer = binaryReader . ReadBytes ( imageHeaderSize ) ;
52
- var bitCountRaw = ( biBitCount < 9 ) ? 4 * Math . Pow ( 2 , biBitCount ) : 0 ;
53
- var bitCount = Math . Truncate ( bitCountRaw ) ;
54
- var colorTableSize = Convert . ToUInt32 ( bitCount ) ;
55
- using ( var ms = new MemoryStream ( ) )
54
+ case ThumbnailInfo . BmpType :
55
+
56
+ for ( var intCnt = 0 ; intCnt < byteCount ; intCnt ++ )
56
57
{
57
- using var binaryWriter = new BinaryWriter ( ms ) ;
58
- binaryWriter . Write ( Convert . ToUInt16 ( 0x4d42 ) ) ;
59
- binaryWriter . Write ( 54u + colorTableSize + biSizeImage ) ;
60
- binaryWriter . Write ( default ( ushort ) ) ;
61
- binaryWriter . Write ( default ( ushort ) ) ;
62
- binaryWriter . Write ( 54u + colorTableSize ) ;
63
- binaryWriter . Write ( bitmapBuffer ) ;
64
-
65
- using var imageTmp2010 = new Bitmap ( ms ) ;
66
- var bytes2010 = ToByteArray ( imageTmp2010 , ImageFormat . Png ) ;
67
-
68
- return bytes2010 ;
58
+ stream . Seek ( thumbInfo . Start , SeekOrigin . Begin ) ;
59
+ var udtHeader = new BitmapHeader
60
+ {
61
+ Size = binaryReader . ReadInt32 ( ) ,
62
+ Width = binaryReader . ReadInt32 ( ) ,
63
+ Height = binaryReader . ReadInt32 ( ) ,
64
+ Planes = binaryReader . ReadInt16 ( ) ,
65
+ BitCount = binaryReader . ReadInt16 ( ) ,
66
+ Compression = binaryReader . ReadInt32 ( ) ,
67
+ SizeImage = binaryReader . ReadInt32 ( ) ,
68
+ XPelsPerMeter = binaryReader . ReadInt32 ( ) ,
69
+ YPelsPerMeter = binaryReader . ReadInt32 ( ) ,
70
+ ClrUsed = binaryReader . ReadInt32 ( ) ,
71
+ ClrImportant = binaryReader . ReadInt32 ( ) ,
72
+ } ;
73
+
74
+ var bytBMPBuff = new byte [ thumbInfo . Length + 1 ] ;
75
+
76
+ if ( udtHeader . BitCount != 8 )
77
+ {
78
+ continue ;
79
+ }
80
+
81
+ var udtColors = new RgbQuad [ 256 ] ;
82
+ for ( int count = 0 ; count < 256 ; count ++ )
83
+ {
84
+ udtColors [ count ] . Blue = binaryReader . ReadByte ( ) ;
85
+ udtColors [ count ] . Green = binaryReader . ReadByte ( ) ;
86
+ udtColors [ count ] . Red = binaryReader . ReadByte ( ) ;
87
+ udtColors [ count ] . Reserved = binaryReader . ReadByte ( ) ;
88
+ }
89
+ stream . Seek ( thumbInfo . Start - 1 , SeekOrigin . Begin ) ;
90
+
91
+ for ( int count = 0 ; count <= thumbInfo . Length ; count ++ )
92
+ bytBMPBuff [ count ] = binaryReader . ReadByte ( ) ;
93
+
94
+ var bmp = new Bitmap ( udtHeader . Width , udtHeader . Height ) ;
95
+ var lngCnt = 0 ;
96
+
97
+ for ( var lngY = 1 ; lngY <= udtHeader . Height ; lngY ++ )
98
+ {
99
+ for ( var lngX = udtHeader . Width ; lngX >= 1 ; lngX -- )
100
+ {
101
+ int lngColor = bytBMPBuff [ bytBMPBuff . GetUpperBound ( 0 ) - lngCnt ] ;
102
+ var udtColor = udtColors [ lngColor ] ;
103
+
104
+ var intRed = Convert . ToInt16 ( udtColor . Red ) ;
105
+ var intGreen = Convert . ToInt16 ( udtColor . Green ) ;
106
+ var intBlue = Convert . ToInt16 ( udtColor . Blue ) ;
107
+ lngColor = ColorTranslator . ToOle ( Color . FromArgb ( intRed , intGreen , intBlue ) ) ;
108
+
109
+ if ( ! RetainBackgroudColor )
110
+ {
111
+ if ( lngColor == ColorTranslator . ToOle ( ColorBlack ) )
112
+ lngColor = ColorTranslator . ToOle ( ColorWhite ) ;
113
+ else if ( lngColor == ColorTranslator . ToOle ( ColorWhite ) )
114
+ lngColor = ColorTranslator . ToOle ( ColorBlack ) ;
115
+ }
116
+
117
+ bmp . SetPixel ( lngX - 1 , lngY - 1 , ColorTranslator . FromOle ( lngColor ) ) ;
118
+ lngCnt ++ ;
119
+ }
120
+ }
121
+
122
+ using var outputStream = new MemoryStream ( ) ;
123
+ bmp . Save ( outputStream , ImageFormat . Png ) ;
124
+ return outputStream . ToArray ( ) ;
69
125
}
70
126
71
- case ThumbnailImageCodes . NULL :
127
+ return new byte [ 0 ] ;
128
+
129
+ case ThumbnailInfo . NullType :
72
130
break ; // DWG file doesn't contain a thumbnail
73
131
}
74
132
#pragma warning restore CC0120
@@ -77,18 +135,38 @@ public override byte[] ExtractThumbnailBytes(Stream stream)
77
135
return new byte [ 0 ] ;
78
136
}
79
137
80
- public static byte [ ] ToByteArray ( Image image , ImageFormat format )
138
+ private struct ThumbnailInfo
139
+ {
140
+ public const byte BmpType = 2 ;
141
+ public const byte PngType = 6 ;
142
+ public const byte NullType = 3 ;
143
+
144
+ public byte Type ;
145
+ public int Start ;
146
+ public int Length ;
147
+ }
148
+
149
+ private struct BitmapHeader
81
150
{
82
- using var ms = new MemoryStream ( ) ;
83
- image . Save ( ms , format ) ;
84
- return ms . ToArray ( ) ;
151
+ public int Size ;
152
+ public int Width ;
153
+ public int Height ;
154
+ public short Planes ;
155
+ public short BitCount ;
156
+ public int Compression ;
157
+ public int SizeImage ;
158
+ public int XPelsPerMeter ;
159
+ public int YPelsPerMeter ;
160
+ public int ClrUsed ;
161
+ public int ClrImportant ;
85
162
}
86
163
87
- private struct ThumbnailImageCodes
164
+ private struct RgbQuad
88
165
{
89
- internal const byte BMP = 2 ;
90
- internal const byte PNG = 6 ;
91
- internal const byte NULL = 3 ;
166
+ public byte Blue ;
167
+ public byte Green ;
168
+ public byte Red ;
169
+ public byte Reserved ;
92
170
}
93
171
}
94
172
}
0 commit comments