This documentation is archived and is not being maintained.

How to: Read a Journal File

The Microsoft Windows Journal Note Reader component provides programmatic read access to files in the Journal format. Journal files have the .jnt file extension. This simple component takes a stream containing a .jnt file and returns a stream containing the file’s content in XML format. The XML returned by the component conforms to the Journal Note Reader schema. This schema is documented in Journal Reader Schema Reference.


The following example reads a .jnt file and adds each page in the file to an InkCanvas. This example assumes that there is a TabControl called pagePanel.

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.IO;
using System.Windows.Ink;
using System.Xml;


        private void LoadInk()
            // Load a Journal file.
            Microsoft.Win32.OpenFileDialog openJnt = new Microsoft.Win32.OpenFileDialog();
            openJnt.Multiselect = false;
            openJnt.Filter = "Journal Files(*.jnt) | *.jnt";


            if (openJnt.FileName == "")

            this.Title = openJnt.FileName;

            //Read in the journal file and load its XML.
            Stream jntFile = openJnt.OpenFile();
            Stream jntXml = Microsoft.Ink.JournalReader.ReadFromStream(jntFile);

            // Get the xml from the JournalReader.
            XmlDocument jntDoc = new XmlDocument();

            //Get all JournalPage nodes in the xml.
            nsmgr = new XmlNamespaceManager(jntDoc.NameTable);
            nsmgr.AddNamespace("jnt", "urn:schemas-microsoft-com:tabletpc:journalreader");
            XmlNodeList pages = jntDoc.DocumentElement.SelectNodes(".//jnt:JournalPage", nsmgr);

            for (int pageCounter = 0; pageCounter < pages.Count; pageCounter++)
                XmlNode page = pages[pageCounter];

                // Create an InkCanvas to hold the ink.
                InkCanvas pageCanvas = new InkCanvas();

                // Create a tab item for each page and name 
                // it according to its page number.
                TabItem tabPage = new TabItem();
                tabPage.Header = "Page " + (pageCounter + 1);

                // Add the InkCanvas to the TabItem.
                tabPage.Content = pageCanvas;

                // Find all the InkWord and Drawings nodes and add the 
                // ink to the InkCanvas.
                XmlNodeList inkWords = 
                    page.SelectNodes(".//jnt:InkWord | .//jnt:Drawing", nsmgr);
                AddInkToCanvas(pageCanvas, inkWords);

                // Add the TabItem representing the current Journal
                // page to the TabControl.

            //Close the streams.

        private void AddInkToCanvas(InkCanvas pageCanvas, XmlNodeList xmlNodes)
            const double cmPerInch = 2.54;

            // The value to multiply to get 
            // device independant pixels.
            const double WPFRatio = 96d / 2540d;

            foreach (XmlNode node in xmlNodes)
                Matrix scalarMatrix = new Matrix();

                // Look for a ScalarTransform element and create a matrix
                // if it is found. The GetValue method is defined below. 
                // ScalarTransform's matrix is in the following format:
                // Mat1 Mat4 Mat7
                // Mat2 Mat5 Mat8
                // Mat3 Mat6 Mat9
                XmlNode scalarTransform = 
                    node.SelectSingleNode("./jnt:ScalarTransform", nsmgr);

                if (scalarTransform != null)
                    scalarMatrix.M11 = GetValue(scalarTransform, "Mat1");
                    scalarMatrix.M12 = GetValue(scalarTransform, "Mat4");
                    scalarMatrix.M21 = GetValue(scalarTransform, "Mat2");
                    scalarMatrix.M22 = GetValue(scalarTransform, "Mat5");

                    // Multiply OffsetX and OffsetY by WPFRatio
                    // to find the WPF coordinates.
                    scalarMatrix.OffsetX = GetValue(scalarTransform, "Mat3") * WPFRatio;
                    scalarMatrix.OffsetY = GetValue(scalarTransform, "Mat6") * WPFRatio;

                // Find the InkObject node.
                XmlNode inkObject = node.SelectSingleNode("./jnt:InkObject", nsmgr);

                if (inkObject != null)
                    // Load the base64 ISF into a MemoryStream and 
                    // create a StrokeCollection.
                    string base64ISF = inkObject.InnerText;
                    MemoryStream isfData = 
                        new MemoryStream(Convert.FromBase64String(base64ISF));
                    StrokeCollection strokes = new StrokeCollection(isfData);

                    // Journal saves the ink in English Metric Units
                    // so convert the ink to inches.
                    ScaleTransform scalar = 
                        new ScaleTransform(cmPerInch, cmPerInch);
                    strokes.Transform(scalar.Value, false);

                    if (!scalarMatrix.IsIdentity)
                        // Apply the accompying ScalarMatrix to the strokes.
                        strokes.Transform(scalarMatrix, false);

                    //Add the ink to the page.



        // Converts the value of ScalarTransform's
        // attribute to a double.
        private double GetValue(XmlNode node, string valueName)
            string nodeValue = node.Attributes.GetNamedItem(valueName).Value;
            return Convert.ToDouble(nodeValue);

Compiling the Code

To compile the code, add a reference to the Microsoft.Ink.JournalReader.dll assembly.