New HTML5 Zero Footprint DICOM Viewer Article on CodeProject

The demand for zero footprint applications is growing rapidly, especially in the healthcare industry with the increasing popularity and usage of tablets and mobile devices by healthcare providers. There are many ways to display DICOM images and communicate with a PACS over the web or intranet in a zero footprint manner, but not all applications are created equal. In fact, not all “zero footprint” applications are truly zero footprint. When choosing HTML5 SDKs it is a good idea to check the fine print before selecting a solution.

As part of its recent HTML5 release, LEADTOOLS now includes a Medical HTML5 Add-on Module which includes everything developers need to create zero footprint DICOM Viewers that run on any browser and platform that supports HTML5. Not only can it be used to display DICOM images, but it includes fast, client-side window leveling and series stack, setting it apart as the fastest HTML5 DICOM viewer available. Also included are RESTful web services that can query and retrieve from your local archive or any PACS using DICOM communication.

For more details on this powerful new product, check out our latest article on The Code Project which explains the technology that make it the fastest and best zero footprint application framework on the market!

Thanks,
Otis Goodwin

Posted in HTML5 | Tagged , , , , , , | Leave a comment

Using LEADTOOLS HTML5 Viewer in Windows Metro Post #2: Annotations

In my last post, I introduced our new LEADTOOLS HTML5 SDK and showed how to create a basic imaging application for Windows Metro. This week, I want to take things a step further and create a Metro application that takes advantage of our HTML5 Annotations. If you missed my previous post, you might benefit from taking a quick peek at it to familiarize yourself with the basic concepts I covered last time.

Let’s jump right in and start coding! The first thing we need to do is create a new JavaScript Metro project in VS2011. Next, we need to add the LEADTOOLS JavaScript files to our HTML (default.html). To add them to the project, I copy them into the ‘js’ folder that is generated when the Visual Studio project is created. It is important we add these files to the project so that they can be included in the application package.

<script type="text/javascript" src="/js/Leadtools.js"></script>
<script type="text/javascript" src="/js/Leadtools.Controls.js"></script>
<script type="text/javascript" src="/js/Leadtools.Annotations.Core.js"></script>
<script type="text/javascript" src="/js/Leadtools.Annotations.Rendering.js"></script>
<script type="text/javascript" src="/js/Leadtools.Annotations.Designers.js"></script>
<script type="text/javascript" src="/js/Leadtools.Annotations.Automation.js"></script>

The next step is to create the actual viewer element and the combobox for selecting the various annotation objects. Adding the viewer is as simple as creating a div and giving it a unique ID. This div will serve as the parent container for the viewer.

<body>
   <p>LEADTOOLS HTML5 SDK in Metro!</p>
   <select id="currentObjectIdSelect"></select>
   <div id="imageViewerDiv" style="width: 600px; height: 600px"></div>
</body>

Let’s switch to the JavaScript code and add what’s needed for initializing the viewer and handling the annotations. The InitViewer function is responsible for creating the viewer and loading our default image. InitAnnotations sets up the LEADTOOLS automated annotation functionality. Just like our Winforms, WPF and Silverlight Annotation SDKs, the HTML5 library provides two basic types of annotation frameworks: automated and non-automated. Non-automated annotations allow you to customize the creation and interaction of annotations. This provides a low-level control to the developer, but also requires that the developer implement most of the behavior-related code. Automated annotations use an ‘automation’ object to control the creation and interaction of annotations. All of the behavior-related code is handled internally, but you are still provided with various options such as the ability to change default properties. Because of its simplicity, automated annotations are the preferred option for most applications written by our customers.

var imageError = function (sender, e) {
   // Get the image element
   var imageElement = e.get_nativeElementEvent().srcElement;
   console.log("Error opening: " + imageElement.src);
};

function InitAnnotations(viewer) {
   // Create an instance of the Automation control object that works with 
   // LEADTOOLS ImageViewer. 
   // This is also an interactive mode that we need to use
   var imageViewerAutomationControl = 
      new Leadtools.Annotations.Automation.ImageViewerAutomationControl(viewer);

   // create and set up the automation manager
   var manager = new Leadtools.Annotations.Automation.AnnAutomationManager();

   //Create the default annotations objects
   manager.createDefaultObjects();

   var currentObjectIdSelect = document.getElementById("currentObjectIdSelect");

   var automationObjCount = manager.get_objects().get_count();
   for (var i = 0; i < automationObjCount; i++) {
      // Get the object
      var automationObj = manager.get_objects().get_item(i);

      // Add its name to the select element
      var name = automationObj.get_name();
      var id = automationObj.get_id();
      currentObjectIdSelect.options[currentObjectIdSelect.options.length] = 
         new Option(name, id);
   }

   // Hook to its change event
   currentObjectIdSelect.addEventListener("change", function () {
      // Get the object ID
      var id = parseInt(
         currentObjectIdSelect.options[currentObjectIdSelect.selectedIndex].value);
      // Set it as the current object in the manager
      manager.set_currentObjectId(id);
   });

   // When the current object ID changes, we need to update our select
   manager.add_currentObjectIdChanged(function (sender, e) {
      var currentObjectId = manager.get_currentObjectId();
      for (var i = 0; i < currentObjectIdSelect.options.length; i++) {
         var id = parseInt(currentObjectIdSelect.options[i].value);
         if (id === currentObjectId) {
            currentObjectIdSelect.selectedIndex = i;
            break;
         }
      }
   });

   //Set the viewer interactive mode
   viewer.set_defaultInteractiveMode(imageViewerAutomationControl);

   // set up the automation (will create the container as well)
   var _automation = new Leadtools.Annotations.Automation.AnnAutomation(
      manager, imageViewerAutomationControl);

   // set up this automation as the active one
   _automation.set_active(true);
}

function InitViewer() {
   // Create the viewer
   var createOptions = new Leadtools.Controls.ImageViewerCreateOptions(
      "imageViewerDiv", "myViewer");
   viewer = new Leadtools.Controls.ImageViewer(createOptions);
   viewer.add_imageError(imageError);
   viewer.set_imageUrl("http://demo.leadtools.com/HTML5/images/pngimage.png");

   InitAnnotations(viewer);
}

The last step is to call the InitViewer function. This function should be called from the app.onactivated event which is automatically generated by Visual Studio when a blank project is created.

app.onactivated = function (eventObject) {
   if (eventObject.detail.kind === 
         Windows.ApplicationModel.Activation.ActivationKind.launch) {
      if (eventObject.detail.previousExecutionState !== 
            Windows.ApplicationModel.Activation.ApplicationExecutionState.terminated) {
         // TODO: This application has been newly launched. Initialize 
         // your application here.
         InitViewer();
      } else {
         // TODO: This application has been reactivated from suspension. 
         // Restore application state here.
         InitViewer();
      }
      WinJS.UI.processAll();
   }
};

If you run the application, you should see something like the screenshot below. In this example, we populated the combobox with all of the the default annotations objects but the AnnAutomationManager object allows you to customize which objects are available, as well as the ability to create custom annotations. Visit our online HTML5 Annotations demo for a complete example that uses our HTML5 SDK. In the coming weeks, I will be discussing other features of our HTML5 SDK so stay tuned.



The complete project I created in this post can be downloaded here.

Thanks,
Otis Goodwin

Posted in Document Imaging, General Imaging | Tagged , , , , , , , | Leave a comment

Using LEADTOOLS HTML5 Viewer in Windows Metro

Over the last month, I’ve touched on two hot topics in the developer community: Windows Metro and HTML5. With the recent release of our HTML5 SDK, I wanted to write a more detailed tutorial about a lesser known use for HTML5 and JavaScript. HTML5 isn’t just for web pages — you can actually create a Windows Metro application using HTML5 and I’ll show you how to do it below using LEAD’s newest product.

My first objective was to create a simple Metro application that would load and display an image using our HTML5 viewer control. I fired up Visual Studio, created a new JavaScript Metro application, and I was ready to start coding. The first step was to add the LEADTOOLS JavaScript files to my HTML.

<script type="text/javascript" src="/js/Leadtools.js"></script>
<script type="text/javascript" src="/js/Leadtools.Controls.js"></script> 

The next step was to create the actual viewer element. Adding the viewer is as simple as creating a div and giving it a unique ID. This div will serve as the parent container for the viewer.

<div id="imageViewerDiv" style="width: 600px; height: 600px"></div>

Then I created a new instance of the viewer, passing the id of the div element from earlier with a simple JavaScript function

function InitViewer() {
   // Create the viewer
   var createOptions = new Leadtools.Controls.ImageViewerCreateOptions(
         "imageViewerDiv", "myViewer");
   viewer = new Leadtools.Controls.ImageViewer(createOptions);
   viewer.add_imageError(imageError);
   viewer.set_imageUrl("http://demo.leadtools.com/HTML5/images/pngimage.png");
}
var imageError = function (sender, e) {
   // Get the image element
   var imageElement = e.get_nativeElementEvent().srcElement;
   console.log("Error opening: " + imageElement.src);
};

The ImageViewerCreateOptions class is used to specify how the viewer will be created, and these options are passed to the ImageViewer constructor. Additionally, I added the ImageError event which provides some extra information if an image cannot be loaded (e.g. incorrect URL/filename, corrupt file, etc.). The last line of course sets the URL of the image we want to display in the viewer.

The InitViewer function should be called from the app.onactivated event which is automatically generated by Visual Studio when a blank project is created.

app.onactivated = function (eventObject) {
   if (eventObject.detail.kind === 
         Windows.ApplicationModel.Activation.ActivationKind.launch) {
      if (eventObject.detail.previousExecutionState !== 
            Windows.ApplicationModel.Activation.ApplicationExecutionState.terminated) {
         // TODO: This application has been newly launched. Initialize 
         // your application here.
         InitViewer();
      } else {
         // TODO: This application has been reactivated from suspension. 
         // Restore application state here.
         InitViewer();
      }
      WinJS.UI.processAll();
   }
};

After those simple steps, I was ready to run my project and I was happy to see an image loaded in my viewer!



That was pretty easy, but frankly, it doesn’t do much more than a standard img tag. This is where it gets fun, because just like the viewers in our other interfaces, the HTML5 viewer supports various interactive modes, size modes, image processing, annotations an more. For the sake of this simple example I’ll stick to interactive and size modes. The interactive modes enable mouse and multi-touch gesture actions such as magnify glass, pinch and zoom, pan, etc.; and the size modes control how the image is scaled or stretched in relation to the viewer.

The first step was two add some combo boxes in the HTML to make it easy to choose from the various interactive and size modes.

<p>Interactive Mode:</p>
   <select id="_cmbInteractiveMode" name="select" onchange="UpdateInteractiveMode();">
      <option>None</option>
      <option>Pan</option>
      <option>ZoomTo</option>
      <option>Mag Glass</option>
      <option>Center At</option>
      <option>Rubberband</option>
   </select>
   <p>Size Mode:</p>
   <select id="_cmbSizeMode" name="select" onchange="UpdateSizeMode();">
      <option>None</option>
      <option>Fit</option>
   </select>
   <div id="imageViewerDiv" style="width: 600px; height: 600px"></div>

As you can see, I subscribed to the onchange events so that I could update the selected option in the viewer. Next, I added their respective event handlers to the JavaScript which call set_sizeMode and set_defaultInteractiveMode with the desired options. While there are many interactive and size modes available, I chose a few of the most popular ones to get an idea of how they work. There is even support for creating custom interactive modes should you have a need for that.

function UpdateSizeMode() {
   var element = document.getElementById('_cmbSizeMode');
   var mode = element.options[element.selectedIndex].innerHTML;
   switch (mode) {
      case "Fit":
         viewer.set_sizeMode(Leadtools.Controls.ImageViewerSizeMode.fit);
         break;
      default:
         viewer.set_sizeMode(Leadtools.Controls.ImageViewerSizeMode.none);
         break;
   }
}

function UpdateInteractiveMode() {
   var element = document.getElementById('_cmbInteractiveMode');
   var mode = element.options[element.selectedIndex].innerHTML;
   switch (mode)
   {
      case "Pan":
         viewer.set_defaultInteractiveMode(
            new Leadtools.Controls.ImageViewerPanZoomInteractiveMode);
         break;
      case "ZoomTo":
         viewer.set_defaultInteractiveMode(
            new Leadtools.Controls.ImageViewerZoomToInteractiveMode);
         break;
      case "Mag Glass":
         viewer.set_defaultInteractiveMode(
            new Leadtools.Controls.ImageViewerMagnifyGlassInteractiveMode);         
         break;
      case "Center At":
         viewer.set_defaultInteractiveMode(
            new Leadtools.Controls.ImageViewerCenterAtInteractiveMode);
         break;
      case "Rubberband":
         viewer.set_defaultInteractiveMode(
            new Leadtools.Controls.ImageViewerRubberBandInteractiveMode);
         break;
      default:
         viewer.set_defaultInteractiveMode(
            new Leadtools.Controls.ImageViewerNoneInteractiveMode);
         break;
   }
}

Running the project with the updated code allows me to specify various interactive and size modes.



Okay, at first I said I was only going to show interactive and size modes so please forgive me for getting carried away with my new toy! Image processing is a foundational feature of LEADTOOLS so I would be remiss to not show a couple of the HTML5 viewer’s image processing effects. Here is the HTML and JavaScript code for adding two buttons that flip and rotate the image.

<input id="_btnFlip" type="button" value="Flip" onclick="Flip();" />
<input id="_btnRotate" type="button" value="Rotate" onclick="Rotate();" />


function Flip() {
   viewer.set_flip(!viewer.get_flip());
}

function Rotate() {
   viewer.set_rotateAngle(viewer.get_rotateAngle() + 15);
}


As I mentioned before, there are a lot more features in the new HTML5 SDK such as annotations, RESTful web services, medical viewer, and much more which I plan on covering in future posts. For the developers looking to create Metro applications using C++, C#, and VB, stay tuned as a full-featured Metro SDK is in the works.

The complete project I created in this post can be downloaded here.

Thanks,
Otis Goodwin

Posted in General Imaging | Tagged , , , , | Leave a comment

New HTML5 Add-ons Are Here!

After several posts and sneak peeks, LEAD’s first HTML5 SDK is here! For the benefit of those who may not have been keeping up with our blog, here’s a brief overview of the features:

These features and more are sold within two add-on modules: one for document and one for medical. As always, this product is free to evaluate so download a the latest version and check out our tutorial on The Code Project to see how easy it is to make powerful HTML5 imaging apps with LEADTOOLS!

Thanks,
Otis Goodwin

Posted in HTML5 | Tagged , , , , , , , , , , , | Leave a comment

OCR: More Than Just Text

OCR is a hot topic around LEAD at the moment. In addition to our recent Code Project Tutorial and blog post about using OCR in a distributed application, LEAD just released some major updates to its Advantage OCR engine.

Most customers are using OCR for one of three reasons:

  1. They want to extract the raw text from an image. For example, using Forms Recognition and Processing to extract a specific field such as address, name, phone number, etc.
  2. They want to archive a digital copy of the document with searchable text. For eample: text only or image over text PDF and PDF/A.
  3. They want to create an editable document from an image. For example, Microsoft Word DOC or DOCX supports both images and text within the same file and is easily editable by a number of proprietary and open-source applications.
To handle these typical scenarios, there are two primary components of any OCR engine. First and foremost, it must be able to accurately recognize all of the text in the image. If all you need is the raw text data as in #1 above, you could stop there. However, this level of recognition is insufficient if your objective is to archive or publish a well formatted PDF file or to save a Word document for editing. Recognizing formatted text is a very complex algorithm that must determine the font face, size, styling (i.e. italics, bold etc.), line information, spacing and more. In my experience, formatted text recognition is where you really start to see different engines show their strengths and weaknesses.

As as example, check out the screenshots below. Figure 1 represents the original image to be recognized; it uses a serifed, mono-spaced font with a slight skew angle, dots to clean up, and two columns of text. Notice in Figure 2 — which shows a third party OCR Engine — that the text was recognized correctly, but had several errors in the formatting. The most obvious error is in the spacing between words and incorrect carriage returns. Less noticeable, but just as important, is that it returned a sans-serif, proportional font with errors in the styling. Figure 3 shows the output with LEADTOOLS’ latest Advantage OCR engine, which is nearly perfect.

Figure 1: Original TIFF


Figure 2: Low quality formatting from some engines


Figure 3: LEADTOOLS Advantage OCR Engine


“That’s great, but why should I care if I only need raw text?”

That’s an intuitive and valid question if you are only concerned with raw text extraction. If getting the font, style and spacing correct isn’t a deciding factor, what is? Nine times out of ten it will come down to speed. Thankfully, we have programmers like you in mind! The LEADTOOLS Advantage OCR Engine provides optimization options that bypass the formatted text recognition, resulting in an average speed increase of 15-20%. Who said you can’t make everyone happy?

Thanks,
Otis Goodwin
Posted in Document Imaging, OCR | Tagged , , , , , , , , , | 1 Comment