Skip to content

Instantly share code, notes, and snippets.

@mdelanno
Last active August 29, 2015 13:56
Show Gist options
  • Save mdelanno/8962894 to your computer and use it in GitHub Desktop.
Save mdelanno/8962894 to your computer and use it in GitHub Desktop.
Imports System
Imports System.Drawing
Imports System.Drawing.Imaging
Imports System.IO
Imports System.Runtime.InteropServices
Imports System.Windows.Forms
''' <summary>
''' Permet d'extraire l'image bitmap de l'aperçu d'un fichier .dwg.
''' </summary>
''' <remarks></remarks>
Class DwgThumbnailReader
''' <summary>
''' Type de miniature qu'on peut trouver dans un fichier .dwg
''' </summary>
''' <remarks></remarks>
Private Enum ThumbnailObjectType
Title = 1
Bmp = 2
Wmf = 3
Png = 6 ' >= 2013
End Enum
''' <summary>
''' Structure utilisée pour chaque objet "miniature"
''' </summary>
''' <remarks></remarks>
<StructLayout(LayoutKind.Sequential)> _
Private Structure IMGREC
Public bytType As Byte
Public lngStart As Integer
Public lngLen As Integer
End Structure
<StructLayout(LayoutKind.Sequential)> _
Private Structure RGBQUAD
Public rgbBlue As Byte
Public rgbGreen As Byte
Public rgbRed As Byte
Public rgbReserved As Byte
End Structure
Public Shared Function GetThumbnail(fileName As String) As Image
Dim img As Image = Nothing
Dim bytCnt As Byte
Dim lngImgLoc As Integer
Dim intCnt As Short
Dim udtRec As IMGREC
Using fs As FileStream = File.OpenRead(fileName)
Using br As BinaryReader = New BinaryReader(fs)
fs.Seek(13, SeekOrigin.Begin)
' Position de la sentinelle
lngImgLoc = br.ReadInt32()
fs.Seek(lngImgLoc + 20, SeekOrigin.Begin)
' Nombre de miniatures
bytCnt = br.ReadByte()
If bytCnt > 1 Then
For intCnt = 0 To bytCnt - 1
udtRec.bytType = br.ReadByte()
' Début des données de l'image
udtRec.lngStart = br.ReadInt32()
' Taille des données de l'image
udtRec.lngLen = br.ReadInt32()
Select Case udtRec.bytType
Case ThumbnailObjectType.Bmp
' L'entête du fichier Bitmap n'est pas inclus dans les données encapsulées dans le .dwg.
' On doit donc le recréer.
' On saute biSize (4 octets), biWidth (4 octets), biHeight (4 octets), biPlanes (2 octets)
fs.Seek(udtRec.lngStart + 14, SeekOrigin.Begin)
Dim biBitCount As UShort = br.ReadUInt16()
' Saute biCompression (4 octets)
fs.Seek(4, SeekOrigin.Current)
Dim biSizeImage As UInt32 = br.ReadUInt32()
' On revient au début de la section contenant les données de l'image
fs.Seek(udtRec.lngStart, SeekOrigin.Begin)
Dim bitmapBuffer As Byte() = br.ReadBytes(udtRec.lngLen)
Dim colorTableSize As UInt16
If biBitCount < 9 Then
colorTableSize = 4 * Math.Pow(2, biBitCount)
End If
Using ms As New MemoryStream
Using bw As New BinaryWriter(ms)
' Nombre "magique" du format BMP (BM en ASCII)
bw.Write(CUShort(&H4D42))
' Taille en octet du fichier BMP
' Entête fichier : 14 octets + Entête image : 40 octets = 54
bw.Write(CInt(54 + colorTableSize + biSizeImage))
' 4 octets "réservés"
bw.Write(CUShort(0))
bw.Write(CUShort(0))
' Position où commence les informations sur les pixels de l'image
bw.Write(54 + colorTableSize)
bw.Write(bitmapBuffer)
Return New Bitmap(ms)
End Using
End Using
Case ThumbnailObjectType.Png
fs.Seek(udtRec.lngStart, SeekOrigin.Begin)
Using ms As New MemoryStream
CopyTo(fs, ms)
Return Image.FromStream(ms)
End Using
End Select
Next
End If
End Using
End Using
End Function
Public Shared Function CopyTo(source As Stream, destination As Stream) As Long
Dim buffer As Byte() = New Byte(2047) {}
Dim bytesRead As Integer
Dim totalBytes As Long = 0
While (bytesRead = source.Read(buffer, 0, buffer.Length))
destination.Write(buffer, 0, bytesRead)
totalBytes += bytesRead
End While
Return totalBytes
End Function
End Class
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment