Hace poco me encontré con este problema y después de mirar diferentes ejemplos y documentación llegue a la siguiente solución.
En documentos RTF las imágenes incrustadas se identifican con un tag “{\pict\”. Solo hay que buscarlo y extraer de dicho tag la cadena hexadecimal que guarda la información de la imagen, transformarla a un array binario y cargarlo en un nuevo objeto imagen con las dimensiones que también hemos extraído del tag.
Espero que a alguien le sea útil. Al final del código os dejo el proyecto ejemplo para descargar.
Imports System.IO
Imports System.Text
Public Class Form1
#Region "Variables y Constantes"
'twip (TWentIeth of a Point) es un punto, una unidad de medida de pantalla.
'Segun documentacion microsoft: http://www.microsoft.com/en-us/download/details.aspx?id=10725
'En un rtf el ancho y el largo de la imagen se guarda en twips
'Un twip equivale aprox. a 26.15 pixels
Const TWIP As Decimal = 26.450704225352109
#End Region
#Region "Eventos"
Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles Me.Load
Me.RichTextBox1.LoadFile("c:\documento.rtf")
End Sub
Private Sub ButtonExtraer_Click(sender As System.Object, e As System.EventArgs) Handles ButtonExtraer.Click
'Extraemos los datos
'-------------------
Dim imagenHex As String
imagenHex = ExtraerImagenHexadecimal(RichTextBox1.Rtf)
Dim elementos As String()
elementos = ExtraerDatosImagen(RichTextBox1.Rtf)
Dim ImgWidth As Integer = (CInt(elementos(3).Replace("picw", "")) / TWIP)
Dim ImgHeight As Integer = (CInt(elementos(4).Replace("pich", "")) / TWIP)
Dim imagenBuffer As Byte()
imagenBuffer = PasarABinario(imagenHex)
'Generamos y Exportamos la imagen
'--------------------------------
Dim image As Image
Dim MemoryStream As Stream = New MemoryStream(imagenBuffer)
image = System.Drawing.Image.FromStream(MemoryStream)
Dim rect As New Rectangle(0, 0, ImgWidth, ImgHeight)
Dim thumb As Bitmap = New Bitmap(ImgWidth, ImgHeight)
Dim pint As Graphics = Graphics.FromImage(thumb)
pint.DrawImage(image, rect)
thumb.Save("c:\Imagen.jpg", System.Drawing.Imaging.ImageFormat.Jpeg)
MemoryStream.Close()
End Sub
#End Region
#Region "Procediminetos y Funciones"
'''
''' Extrae la imagen en hexadecimal del texto del rtf
'''
'''
'''
'''
Public Function ExtraerImagenHexadecimal(ByVal texto As String)
Dim pictTagIdx As Integer = texto.IndexOf("{\pict\")
Dim startIndex As Integer = texto.IndexOf(" ", pictTagIdx) + 1
Dim endIndex As Integer = texto.IndexOf("}", startIndex)
Return texto.Substring(startIndex, endIndex - startIndex)
End Function
'''
''' Extrae los Datos de la imagen
'''
'''
'''
'''
Public Function ExtraerDatosImagen(ByVal texto As String) As String()
Dim pictTagIdx As Integer = texto.IndexOf("{\pict\")
Dim startIndex As Integer = texto.IndexOf(" ", pictTagIdx)
Dim endIndex As Integer = texto.IndexOf("}", startIndex)
Dim cadena As String
cadena = texto.Substring(pictTagIdx, startIndex - pictTagIdx)
Dim elementos As String() = cadena.Split("\")
Return elementos
End Function
'''
''' Pasa la cadena Hexadecimal a un array binario
'''
'''
'''
'''
Public Function PasarABinario(ByVal imageDataHex As String) As Byte()
If imageDataHex Is Nothing Or imageDataHex.Trim = "" Then
Throw New ArgumentNullException("imageDataHex")
End If
Dim hexDigits As Integer = imageDataHex.Length
Dim dataSize As Integer = hexDigits / 2
Dim imageDataBinary(dataSize) As Byte
Dim hex As New StringBuilder(2)
Dim dataPos As Integer = 0
Dim c As Char
For i As Integer = 0 To hexDigits - 1
c = imageDataHex(i)
If Char.IsWhiteSpace(c) Then
Continue For
End If
hex.Append(imageDataHex(i))
If hex.Length = 2 Then
imageDataBinary(dataPos) = Byte.Parse(hex.ToString(), System.Globalization.NumberStyles.HexNumber)
dataPos = dataPos + 1
hex.Remove(0, 2)
End If
Next
Return imageDataBinary
End Function
#End Region
End Class