Deriving from RasterImage and Serialization
The RasterImage interface and the RasterImage class implement the ISerializable interface and thus support standard .NET serialization.
Serialization is the process of converting the state of an object into a form that can be persisted or transported. The complement of serialization is deserialization, which converts a stream into an object. Together, these processes allow data to be easily stored and transferred.
You can easily save and restore the image data of a RasterImage object by saving/loading the image back into one of the numerous file image formats supported by LEADTOOLS. However, by doing so, you lose any data that is not supported by the image file format. For example, the region data you currently have in the image is not supported by any file image format. The metadata (tags, markers and comments) are supported by some formats but not all.
Serialization solves these problems by saving everything in the image and later deserializing back into its original state. Moreover, when you derive your own class from RasterImage, you can extend the serialization mechanism to support saving/restoring your own data inside the image.
The RasterImage supports both binary and XML serialization.
You can use binary serialization to share the RasterImage object between different applications by serializing it to the Clipboard. You can serialize the RasterImage to a stream, to a disk, to memory, over the network, and so forth. Remoting uses binary serialization to pass objects "by value" from one computer or application domain to another.
Binary serialization is the most efficient way to serialize a RasterImage object both in speed of serialization/deserialization as well using less space for the object data.
Examples of binary serialization:
Imports System.IOImports System.Runtime.Serialization.Formatters.BinaryImports LeadtoolsImports Leadtools.CodecsPrivate Sub BinarySerializationTest()Dim codecs As RasterCodecs = New RasterCodecs()' Load an imageDim image1 As RasterImage = codecs.Load("C:\Users\Public\Documents\LEADTOOLS Images\Image1.cmp")' Use the binary formatterDim formatter As BinaryFormatter = New BinaryFormatter()' Serialize this image into a memory streamDim ms As MemoryStream = New MemoryStream()formatter.Serialize(ms, image1)' We are done with the imageimage1.Dispose()' Move back to the beginning of the streamms.Position = 0' De-serialize the image backDim image2 As RasterImage = CType(If(TypeOf formatter.Deserialize(ms) Is RasterImage, formatter.Deserialize(ms), Nothing), RasterImage)' re-save the imagecodecs.Save(image2, "C:\Users\Public\Documents\LEADTOOLS Images\Image1_Serialized.bmp", RasterImageFormat.Bmp, 24)' Clean upimage2.Dispose()ms.Close()codecs.Dispose()End Sub
using System.IO;using System.Runtime.Serialization.Formatters.Binary;using Leadtools;using Leadtools.Codecs;private void BinarySerializationTest(){RasterCodecs codecs = new RasterCodecs();// Load an imageRasterImage image1 = codecs.Load(@"C:\Users\Public\Documents\LEADTOOLS Images\Image1.cmp");// Use the binary formatterBinaryFormatter formatter = new BinaryFormatter();// Serialize this image into a memory streamMemoryStream ms = new MemoryStream();formatter.Serialize(ms, image1);// We are done with the imageimage1.Dispose();// Move back to the beginning of the streamms.Position = 0;// De-serialize the image backRasterImage image2 = formatter.Deserialize(ms) as RasterImage;// re-save the imagecodecs.Save(image2, @"C:\Users\Public\Documents\LEADTOOLS Images\Image1_Serialized.bmp", RasterImageFormat.Bmp, 24);// Clean upimage2.Dispose();ms.Close();codecs.Dispose();}
You can also use serialize a RasterImage object to XML. Since XML is an open standard, XML serialization is an attractive choice for sharing a RasterImage object across the Web.
However, since XML is a text format, XML serialization is not recommended to be used with a RasterImage object. The speed of serialization/deserialization is a lot slower than binary serialization and XML serialization uses a lot more space for the object data.
Serialization Example (Using the Windows Clipboard) The following example shows you how to copy and paste a RasterImage object to the Windows clipboard using serialization. This example assumes that you have added the code to a Form and call the method created in the example from the constructor or another method on the form.
Imports SystemImports System.Windows.FormsImports LeadtoolsImports Leadtools.CodecsImports Leadtools.WinFormsPrivate panel1 As PanelPrivate loadButton As ButtonPrivate clearButton As ButtonPrivate copyButton As ButtonPrivate pasteButton As ButtonPrivate rasterImageViewer1 As RasterImageViewerPrivate codecs1 As RasterCodecsPrivate Sub ClipboardTest()' Add the controls to the form' 1. RasterImageViewer control' 2. Load button to load an image into the viewer' 3. Clear button to reset the viewer's image.' 3. Copy button to copy the image to the clipboard' 4. Paste button to paste the image from the clipboard to the viewer' Create the controlsMe.SuspendLayout()loadButton = New Buttonpanel1 = New Panelpanel1.Dock = DockStyle.Leftpanel1.Width = loadButton.WidthMe.Controls.Add(panel1)loadButton.Text = "Load"loadButton.Location = New Point(0, 0)panel1.Controls.Add(loadButton)loadButton.BringToFront()AddHandler loadButton.Click, AddressOf loadButton_ClickclearButton = New ButtonclearButton.Text = "Clear"clearButton.Location = New Point(0, loadButton.Bottom)panel1.Controls.Add(clearButton)clearButton.BringToFront()AddHandler clearButton.Click, AddressOf clearButton_ClickcopyButton = New ButtoncopyButton.Text = "Copy"copyButton.Location = New Point(0, clearButton.Bottom)panel1.Controls.Add(copyButton)copyButton.BringToFront()AddHandler copyButton.Click, AddressOf copyButton_ClickpasteButton = New ButtonpasteButton.Text = "Paste"pasteButton.Location = New Point(0, copyButton.Bottom)panel1.Controls.Add(pasteButton)pasteButton.BringToFront()AddHandler pasteButton.Click, AddressOf pasteButton_ClickrasterImageViewer1 = New RasterImageViewerrasterImageViewer1.Dock = DockStyle.FillControls.Add(rasterImageViewer1)rasterImageViewer1.BringToFront()Me.ResumeLayout()' Initialize the codecs objectcodecs1 = New RasterCodecs' Update our user interfaceUpdateMyUserInterface()End SubPrivate Sub UpdateMyUserInterface()' Update the buttons depending on the application state' The Clear button is enabled if we have an imageclearButton.Enabled = (Not rasterImageViewer1.Image Is Nothing)' The Copy button is enabled if we have an imagecopyButton.Enabled = (Not rasterImageViewer1.Image Is Nothing)' The paste button is enabled if we have a valid clipboard formatDim data As IDataObject = Clipboard.GetDataObject()pasteButton.Enabled = data.GetDataPresent(GetType(RasterImage))End SubPrivate Sub loadButton_Click(ByVal sender As Object, ByVal e As EventArgs)' Load a new image into the viewerDim dlg As New OpenFileDialogdlg.Filter = "All Files|*.*"If (dlg.ShowDialog(Me) = DialogResult.OK) ThenTryrasterImageViewer1.Image = codecs1.Load(dlg.FileName)Catch ex As ExceptionMessageBox.Show(Me, ex.Message)Finally' Update the user interfaceUpdateMyUserInterface()End TryEnd IfEnd SubPrivate Sub clearButton_Click(ByVal sender As Object, ByVal e As EventArgs)' Delete the image in the viewerrasterImageViewer1.Image = Nothing' Update the user interfaceUpdateMyUserInterface()End SubPrivate Sub copyButton_Click(ByVal sender As Object, ByVal e As EventArgs)' Copy the image in the viewer into the clipboardClipboard.SetDataObject(rasterImageViewer1.Image, True)' Update the user interfaceUpdateMyUserInterface()End SubPrivate Sub pasteButton_Click(ByVal sender As Object, ByVal e As EventArgs)' Paste the image from the clipboard into the viewerDim data As IDataObject = Clipboard.GetDataObject()rasterImageViewer1.Image = CType(data.GetData(GetType(RasterImage)), RasterImage)' Update the user interfaceUpdateMyUserInterface()End Sub
using System;using System.Windows.Forms;using Leadtools;using Leadtools.Codecs;using Leadtools.WinForms;private Panel panel1;private Button loadButton;private Button clearButton;private Button copyButton;private Button pasteButton;private RasterImageViewer rasterImageViewer1;private RasterCodecs codecs1;private void ClipboardTest(){// Add the controls to the form// 1. RasterImageViewer control// 2. Load button to load an image into the viewer// 3. Clear button to reset the viewer's image.// 3. Copy button to copy the image to the clipboard// 4. Paste button to paste the image from the clipboard to the viewer// Create the controlsthis.SuspendLayout();loadButton = new Button();panel1 = new Panel();panel1.Dock = DockStyle.Left;panel1.Width = loadButton.Width;this.Controls.Add(panel1);loadButton.Text = "Load";loadButton.Location = new Point(0, 0);panel1.Controls.Add(loadButton);loadButton.BringToFront();loadButton.Click += new EventHandler(loadButton_Click);clearButton = new Button();clearButton.Text = "Clear";clearButton.Location = new Point(0, loadButton.Bottom);panel1.Controls.Add(clearButton);clearButton.BringToFront();clearButton.Click += new EventHandler(clearButton_Click);copyButton = new Button();copyButton.Text = "Copy";copyButton.Location = new Point(0, clearButton.Bottom);panel1.Controls.Add(copyButton);copyButton.BringToFront();copyButton.Click += new EventHandler(copyButton_Click);pasteButton = new Button();pasteButton.Text = "Paste";pasteButton.Location = new Point(0, copyButton.Bottom);panel1.Controls.Add(pasteButton);pasteButton.BringToFront();pasteButton.Click += new EventHandler(pasteButton_Click);rasterImageViewer1 = new RasterImageViewer();rasterImageViewer1.Dock = DockStyle.Fill;Controls.Add(rasterImageViewer1);rasterImageViewer1.BringToFront();this.ResumeLayout();// Initialize the codecs objectcodecs1 = new RasterCodecs();// Update our user interfaceUpdateMyUserInterface();}private void UpdateMyUserInterface(){// Update the buttons depending on the application state// The Clear button is enabled if we have an imageclearButton.Enabled = rasterImageViewer1.Image != null;// The Copy button is enabled if we have an imagecopyButton.Enabled = rasterImageViewer1.Image != null;// The paste button is enabled if we have a valid clipboard formatIDataObject data = Clipboard.GetDataObject();pasteButton.Enabled = data.GetDataPresent(typeof(RasterImage));}private void loadButton_Click(object sender, EventArgs e){// Load a new image into the viewerOpenFileDialog dlg = new OpenFileDialog();dlg.Filter = "All Files|*.*";if(dlg.ShowDialog(this) == DialogResult.OK){try{rasterImageViewer1.Image = codecs1.Load(dlg.FileName);}catch(Exception ex){MessageBox.Show(this, ex.Message);}finally{// Update the user interfaceUpdateMyUserInterface();}}}private void clearButton_Click(object sender, EventArgs e){// Delete the image in the viewerrasterImageViewer1.Image = null;// Update the user interfaceUpdateMyUserInterface();}private void copyButton_Click(object sender, EventArgs e){// Copy the image in the viewer into the clipboardClipboard.SetDataObject(rasterImageViewer1.Image, true);// Update the user interfaceUpdateMyUserInterface();}private void pasteButton_Click(object sender, EventArgs e){// Paste the image from the clipboard into the viewerIDataObject data = Clipboard.GetDataObject();rasterImageViewer1.Image = data.GetData(typeof(RasterImage)) as RasterImage;// Update the user interfaceUpdateMyUserInterface();}
The RasterImage class can be derived from to add user-defined functionality. Derived classes might need to add new class member variables to the class that define this new functionality. The author must add support for serializing these new class member variables in order to participate in the serialization process.
The following example shows MyRasterImage, a class that derives from RasterImage adding two new properties.
Imports System.IOImports System.Runtime.SerializationImports System.Runtime.Serialization.Formatters.BinaryImports LeadtoolsImports Leadtools.CodecsPublic Class MyRasterImageInherits RasterImage' Our new members' We are going to do the serialization ourselvesPrivate _myIntegerData As IntegerPrivate _myStringData As String' AccessorsPublic Property MyIntegerData() As IntegerGetReturn _myIntegerDataEnd GetSet(ByVal Value As Integer)_myIntegerData = ValueEnd SetEnd PropertyPublic Property MyStringData() As StringGetReturn _myStringDataEnd GetSet(ByVal Value As String)_myStringData = ValueEnd SetEnd Property' ConstructorPublic Sub New(ByVal src As RasterImage)MyBase.New(src)_myIntegerData = 0_myStringData = String.EmptyEnd Sub' Serialization codeProtected Sub New(ByVal info As SerializationInfo, ByVal context As StreamingContext)MyBase.New(info, context)' Load our data_myIntegerData = info.GetInt32("MyIntegerData")_myStringData = info.GetString("MyStringData")End SubPublic Overrides Sub GetObjectData(ByVal info As SerializationInfo, ByVal context As StreamingContext)' Always call the base methodMyBase.GetObjectData(info, context)' Save our datainfo.AddValue("MyIntegerData", _myIntegerData)info.AddValue("MyStringData", _myStringData)End SubEnd ClassPrivate Sub MyRasterImageTest()' Load an imageDim codecs As New RasterCodecsDim img As RasterImage = codecs.Load("C:\Users\Public\Documents\LEADTOOLS Images\Image1.cmp")' create a new MyRasterImage instance out of this imageDim myImage As MyRasterImage = New MyRasterImage(img)' Set custom datamyImage.MyIntegerData = 10myImage.MyStringData = "My string"Dim msg As String = String.Format("Before serialization. MyIntegerData = {0}, MyStringData = {1}", myImage.MyIntegerData, myImage.MyStringData)MessageBox.Show(msg)' img is invalid now and should be disposedimg.Dispose()' Serialize myImageDim formatter As New BinaryFormatterDim ms As New MemoryStreamformatter.Serialize(ms, myImage)' dispose myImagemyImage.Dispose()myImage = Nothing' Deserialize back from the streamms.Position = 0myImage = DirectCast(formatter.Deserialize(ms), MyRasterImage)msg = String.Format("After serialization. MyIntegerData = {0}, MyStringData = {1}", myImage.MyIntegerData, myImage.MyStringData)MessageBox.Show(msg)' Clean upms.Close()myImage.Dispose()codecs.Dispose()End Sub
using System.IO;using System.Runtime.Serialization;using System.Runtime.Serialization.Formatters.Binary;using Leadtools;using Leadtools.Codecs;[Serializable]public class MyRasterImage : RasterImage{// Our new members// We are going to do the serialization ourselves[NonSerialized] private int _myIntegerData;[NonSerialized] private string _myStringData;// Accessorspublic int MyIntegerData{get{return _myIntegerData;}set{_myIntegerData = value;}}public string MyStringData{get{return _myStringData;}set{_myStringData = value;}}// Constructorpublic MyRasterImage(RasterImage src) :base(src){_myIntegerData = 0;_myStringData = string.Empty;}// Serialization codeprotected MyRasterImage(SerializationInfo info, StreamingContext context) :base(info, context){// Load our data_myIntegerData = info.GetInt32("MyIntegerData");_myStringData = info.GetString("MyStringData");}public override void GetObjectData(SerializationInfo info, StreamingContext context){// Always call the base methodbase.GetObjectData(info, context);// Save our datainfo.AddValue("MyIntegerData", _myIntegerData);info.AddValue("MyStringData", _myStringData);}}private void MyRasterImageTest(){// Load an imageRasterCodecs codecs = new RasterCodecs();RasterImage img = codecs.Load(@"C:\Users\Public\Documents\LEADTOOLS Images\Image1.cmp");// create a new MyRasterImage instance out of this imageMyRasterImage myImage = new MyRasterImage(img);// Set custom datamyImage.MyIntegerData = 10;myImage.MyStringData = "My string";string msg = string.Format("Before serialization. MyIntegerData = {0}, MyStringData = {1}", myImage.MyIntegerData, myImage.MyStringData);MessageBox.Show(msg);// img is invalid now and should be disposedimg.Dispose();// Serialize myImageBinaryFormatter formatter = new BinaryFormatter();MemoryStream ms = new MemoryStream();formatter.Serialize(ms, myImage);// dispose myImagemyImage.Dispose();myImage = null;// Deserialize back from the streamms.Position = 0;myImage = formatter.Deserialize(ms) as MyRasterImage;msg = string.Format("After serialization. MyIntegerData = {0}, MyStringData = {1}", myImage.MyIntegerData, myImage.MyStringData);MessageBox.Show(msg);// Clean upms.Close();myImage.Dispose();codecs.Dispose();}