Colabora |
Serializar y Deserializar imágenes en XML
Fecha: 17/Ene/2007 (17 Enero 2007)
|
IntroducciónEsta es una pequeña mejora que he realizado sobre una clase ya publicada en esta página anteriormente por Christian Omar Bigentini. Esta clase se puede ver en el siguiente link . Por tanto, lo primero agradecer a Christian su colaboración, que supone la base del código que presento, siendo mi aportación una pequeña parte dentro de dicho código.
ContenidoEn su momento me encontré con la necesidad de transmitir imágenes desde un Servicio Web hacia los clientes y viceversa. Para ello, encontré la clase antes mencionada, que serializa el archivo de imagen en formato XML para enviarlo y lo deserializa en la recepción obteniendo de nuevo la imagen. Al utilizarla me encontré con un par de necesidades que esta clase no cubría: Pues bien, estas son las 2 mejoras que he incluido en la clase. La clase pues, incluye 3 métodos: 2 para convertir la imagen en un nodo XML, uno de ellos sólo recibe la imagen y el otro recibe también un texto que se podrá recuperar en la recepción; y el método que deserializa el nodo XML recibido y devuelve el objeto imagen.
CódigoEste es el código de la clase en Visual Basic: Public Class ConversorImagen Public Shared Function ImageToXMLNode(ByVal imagen As Drawing.Image) As XmlNode Dim oStream As New System.IO.MemoryStream Dim oDom As New XmlDocument Dim mResult As New IO.MemoryStream Dim LenData As Long = 0 Dim Buffer() As Byte Dim oBinaryReader As IO.BinaryReader Dim oXMLTextWriter As XmlTextWriter Dim oStreamReader As IO.StreamReader Dim StrResult As String 'Verifico si existe imagen a serializar If Not imagen Is Nothing Then 'Se graba en Stream para almacenar la imagen en formato binario 'Se conserva el formato de la imagen Dim imgF As Drawing.Imaging.ImageFormat imgF = imagen.RawFormat imagen.Save(oStream, imgF) oStream.Position = 0 LenData = oStream.Length - 1 'Verifico la longitud de datos a serializar If LenData > 0 Then ReDim Buffer(Convert.ToInt32(LenData)) 'Genero Buffer 'Leo los datos binarios oBinaryReader = New IO.BinaryReader(oStream, System.Text.Encoding.UTF8) oBinaryReader.Read(Buffer, 0, Buffer.Length) 'Creo XMLTextWriter y agrego nodo con la imagen oXMLTextWriter = New XmlTextWriter(mResult, System.Text.Encoding.UTF8) oXMLTextWriter.WriteStartDocument() oXMLTextWriter.WriteStartElement("BinaryData") oXMLTextWriter.WriteBase64(Buffer, 0, Buffer.Length) oXMLTextWriter.WriteEndElement() oXMLTextWriter.WriteEndDocument() oXMLTextWriter.Flush() 'posiciono en 0 el resultado mResult.Position = 0 'Pasa el Stream a String y retorna oStreamReader = New IO.StreamReader(mResult, System.Text.Encoding.UTF8) StrResult = oStreamReader.ReadToEnd() oStreamReader.Close() 'Agrego Nuevo Nodo con imagen oDom.LoadXml(StrResult) Return oDom.DocumentElement Else 'En caso de no existir datos retorno el XML con formato vacio oDom.LoadXml("<BinaryData/>") Return oDom.DocumentElement.CloneNode(True) End If Else 'no hay imagen devuelvo el XML Vacio oDom.LoadXml("<BinaryData/>") Return oDom.DocumentElement.CloneNode(True) End If End Function Public Shared Function ImageToXMLNode( _ ByVal imagen As Drawing.Image, _ ByVal nombre As String) As XmlNode Dim oStream As New System.IO.MemoryStream Dim oDom As New XmlDocument Dim mResult As New IO.MemoryStream Dim LenData As Long = 0 Dim Buffer() As Byte Dim oBinaryReader As IO.BinaryReader Dim oXMLTextWriter As XmlTextWriter Dim oStreamReader As IO.StreamReader Dim StrResult As String 'Verifico si existe imagen a serializar If Not imagen Is Nothing Then 'Se graba en Stream para almacenar la imagen en formato binario 'Se conserva el formato de la imagen Dim imgF As Drawing.Imaging.ImageFormat imgF = imagen.RawFormat imagen.Save(oStream, imgF) oStream.Position = 0 LenData = oStream.Length - 1 'Verifico la longitud de datos a serializar If LenData > 0 Then ReDim Buffer(Convert.ToInt32(LenData)) 'Genero Buffer 'Leo los datos binarios oBinaryReader = New IO.BinaryReader(oStream, System.Text.Encoding.UTF8) oBinaryReader.Read(Buffer, 0, Buffer.Length) 'Creo XMLTextWriter y agrego nodo con la imagen oXMLTextWriter = New XmlTextWriter(mResult, System.Text.Encoding.UTF8) oXMLTextWriter.WriteStartDocument() oXMLTextWriter.WriteStartElement("BinaryData") oXMLTextWriter.WriteAttributeString("Nombre", nombre) oXMLTextWriter.WriteBase64(Buffer, 0, Buffer.Length) oXMLTextWriter.WriteEndElement() oXMLTextWriter.WriteEndDocument() oXMLTextWriter.Flush() 'posiciono en 0 el resultado mResult.Position = 0 'Pasa el Stream a String y retorna oStreamReader = New IO.StreamReader(mResult, System.Text.Encoding.UTF8) StrResult = oStreamReader.ReadToEnd() oStreamReader.Close() 'Agrego Nuevo Nodo con imagen oDom.LoadXml(StrResult) Return oDom.DocumentElement Else 'En caso de no existir datos retorno el XML con formato vacio oDom.LoadXml("<BinaryData/>") Return oDom.DocumentElement.CloneNode(True) End If Else 'no hay imagen devuelvo el XML Vacio oDom.LoadXml("<BinaryData/>") Return oDom.DocumentElement.CloneNode(True) End If End Function 'Desserializa XML y retorna la Imágen Public Shared Function XMLNodeToImage(ByVal Nodo As Xml.XmlNode) As Image Dim IntResult As Integer = 0 Dim IntPosition As Integer = 0 Dim LenBytes As Integer = 1024 * 1024 '1024KB - 1MB Lee bloques de 1MB Dim myBytes(LenBytes - 1) As Byte Dim oMem As New IO.MemoryStream Dim oXMLTextReader As Xml.XmlTextReader Dim NodeFound As Boolean = False 'Dim oStreamReader As IO.StreamReader Dim oStreamWriter As IO.StreamWriter Dim oTempMem As New IO.MemoryStream Dim nombre As String = "" Try 'Cargo nodo de texto en Memory Stream ' para almacenar la imagen temporalmente en bytes oStreamWriter = New IO.StreamWriter(oTempMem, System.Text.Encoding.UTF8) oStreamWriter.Write(Nodo.OuterXml) oStreamWriter.Flush() oTempMem.Position = 0 'Cargo un xmlReader con el Memory Stream para leer la imágen almacenada oXMLTextReader = New Xml.XmlTextReader(oTempMem) 'Busco el Nodo en Binario Do While oXMLTextReader.Read If oXMLTextReader.Name = "BinaryData" Then NodeFound = True Exit Do End If Loop 'Verifico si se encontró el Nodo con la imagen If NodeFound Then If oXMLTextReader.HasAttributes Then nombre = oXMLTextReader.GetAttribute("Nombre") End If 'Lo encontro, me muevo a la Posicion Inicial del Stream para leerlo IntPosition = 0 'Intento Leer IntResult = oXMLTextReader.ReadBase64(myBytes, 0, LenBytes) Do While IntResult > 0 'Escribe datos oMem.Write(myBytes, 0, IntResult) 'Limpio el array Array.Clear(myBytes, 0, LenBytes) 'Leo nuevamente IntResult = oXMLTextReader.ReadBase64(myBytes, 0, LenBytes) Loop Try 'Intento crear la Imagen y retornarla si no devuelvo Nothing Dim img As Image img = Bitmap.FromStream(oMem, True, True) If (nombre IsNot Nothing) AndAlso (nombre.Length > 0) Then img.Tag = nombre End If Return img Catch Return Nothing End Try Else 'No encontró el nodo de imágen Return Nothing End If Catch ex As Exception 'Ocurrio un error no contemplado Retorno Nothing Return Nothing End Try End Function End Class
Espero que estas mejoras os sirvan de ayuda. Saludos.
Espacios de nombres usados en el código de este artículo:System.Drawing
|