[med-svn] r20664 - in trunk/packages/orthanc-webviewer/trunk/debian: . JS JS/cornerstone-0.8.4

Sebastien Jodogne jodogne-guest at moszumanska.debian.org
Mon Dec 7 15:27:49 UTC 2015


Author: jodogne-guest
Date: 2015-12-07 15:27:48 +0000 (Mon, 07 Dec 2015)
New Revision: 20664

Added:
   trunk/packages/orthanc-webviewer/trunk/debian/JS/cornerstone-0.8.4/
   trunk/packages/orthanc-webviewer/trunk/debian/JS/cornerstone-0.8.4/LICENSE
   trunk/packages/orthanc-webviewer/trunk/debian/JS/cornerstone-0.8.4/README.md
   trunk/packages/orthanc-webviewer/trunk/debian/JS/cornerstone-0.8.4/cornerstone.css
   trunk/packages/orthanc-webviewer/trunk/debian/JS/cornerstone-0.8.4/cornerstone.js
Removed:
   trunk/packages/orthanc-webviewer/trunk/debian/JS/cornerstone-0.7.1/
Modified:
   trunk/packages/orthanc-webviewer/trunk/debian/changelog
   trunk/packages/orthanc-webviewer/trunk/debian/rules
Log:
Upgrade Cornerstone version: 0.7.1 to 0.8.4

Added: trunk/packages/orthanc-webviewer/trunk/debian/JS/cornerstone-0.8.4/LICENSE
===================================================================
--- trunk/packages/orthanc-webviewer/trunk/debian/JS/cornerstone-0.8.4/LICENSE	                        (rev 0)
+++ trunk/packages/orthanc-webviewer/trunk/debian/JS/cornerstone-0.8.4/LICENSE	2015-12-07 15:27:48 UTC (rev 20664)
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 Chris Hafey (chafey at gmail.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
\ No newline at end of file

Added: trunk/packages/orthanc-webviewer/trunk/debian/JS/cornerstone-0.8.4/README.md
===================================================================
--- trunk/packages/orthanc-webviewer/trunk/debian/JS/cornerstone-0.8.4/README.md	                        (rev 0)
+++ trunk/packages/orthanc-webviewer/trunk/debian/JS/cornerstone-0.8.4/README.md	2015-12-07 15:27:48 UTC (rev 20664)
@@ -0,0 +1,252 @@
+Cornerstone Core
+================
+
+Cornerstone is an open source project with a goal to deliver a complete web based medical imaging platform.  This
+repository contains the Cornerstone Core component which is a lightweight JavaScript library for displaying
+medical images in modern web browsers that support the HTML5 canvas element.
+Cornerstone Core is not meant to be a complete application itself, but instead a component
+that can be used as part of larger more complex applications.  See the
+[CornerstoneDemo](http://chafey.github.io/cornerstoneDemo/) for an example of using the various Cornerstone
+libraries to build a simple study viewer.
+
+Cornerstone Core is agnostic to the actual container used to store image pixels as well as the transport mechanism
+used to get the image data.  In fact, Cornerstone Core itself has no ability to read/parse or load images and instead
+depends on one or more [ImageLoaders](https://github.com/chafey/cornerstone/wiki/ImageLoader) to function.
+The goal here is to avoid constraining developers to work within a single container and transport (e.g. DICOM) since
+images are stored in a variety of formats (including proprietary).  By providing flexibility with respect to the
+container and transport, the highest performance image display may be obtained as no conversion to an alternate
+container or transport is required.  It is hoped that developers feel empowered to load images from any type of image
+container using any kind of transport.  See the
+[CornerstoneWADOImageLoader](https://github.com/chafey/cornerstoneWADOImageLoader) project for an example
+of a DICOM WADO based Image Loader.
+
+Cornerstone Core is agnostic to the exact interaction paradigm being used.  It does not include any mouse, touch or
+keyboard bindings to manipulate the various image properties such as scale, translation or ww/wc.  The goal here
+is to avoid constraining developers using this library to fit into a given ui paradigm.  It is hoped that developers
+are empowered to create new paradigms possibly using new input mechanisms to interact with medical images (e.g.
+[Kinect](http://en.wikipedia.org/wiki/Kinect) or [Accelerometer](http://en.wikipedia.org/wiki/Accelerometer).
+Cornerstone does provide a set of API's allowing manipulation of the image properties via javascript.
+See the [CornerstoneTools](https://github.com/chafey/cornerstoneTools) library for an example of common tools built on top of
+Cornerstone.
+
+Community
+---------
+
+Have questions?  Try posting on our [google groups forum](https://groups.google.com/forum/#!forum/cornerstone-platform).
+
+Live Examples
+---------------
+The best way to see the power of this library is to actually see it in use.
+
+[Click here for a list of examples of using the Cornerstone library.](https://rawgit.com/chafey/cornerstone/master/example/index.html)
+
+Install
+-------
+
+Get a packaged source file:
+
+* [cornerstone.js](https://raw.githubusercontent.com/chafey/cornerstone/master/dist/cornerstone.js)
+* [cornerstone.min.js](https://raw.githubusercontent.com/chafey/cornerstone/master/dist/cornerstone.min.js)
+
+Or install via [Bower](http://bower.io/):
+
+> bower install cornerstone
+
+
+Key Features
+------------
+
+ * HTML5/Javascript based library to easily add interactive medical images to web applications
+ * Serves as a foundation to build more complex medical imaging applications from - enterprise viewer, report viewer, etc.
+ * Supports all HTML5 based browsers including mobile, tablet and desktop
+ * Displays all common medical image formats (e.g. 8 bit grayscale, 16 bit grayscale, RGB color)
+ * High performance image display
+ * Retrieval of images from different systems with different protocols via Image Loader plugin design
+ * API support for changing viewport properties (e.g. ww/wc, zoom, pan, invert)
+
+Build System
+============
+
+This project uses grunt to build the software.
+
+Pre-requisites:
+---------------
+
+NodeJs - [click to visit web site for installation instructions](http://nodejs.org).
+
+grunt-cli
+
+> npm install -g grunt-cli
+
+bower
+
+> npm install -g bower
+
+Common Tasks
+------------
+
+Update dependencies (after each pull):
+> npm install
+
+> bower install
+
+Running the build:
+> grunt
+
+Automatically running the build and unit tests after each source change:
+> grunt watch
+
+Links
+=====
+
+[View the wiki for documentation on the concepts and APIs](https://github.com/chafey/cornerstone/wiki)
+
+[View Roadmap](docs/roadmap.md)
+
+[View Backlog](docs/backlog.md)
+
+[comp.protocols.dicom thread](https://groups.google.com/forum/#!topic/comp.protocols.dicom/_2fMh69GdAM)
+
+[Trello](https://trello.com/b/tGTDIyt4/cornerstone)
+
+[CornerstoneTools](https://github.com/chafey/cornerstoneTools) - A library of common tools that can be used with Cornerstone
+
+[CornerstoneWADOImageLoader ](https://github.com/chafey/cornerstoneWADOImageLoader) - A Cornerstone Image Loader that works with WADO
+
+[dicomParser ](https://github.com/chafey/dicomParser) - A JavaScript library designed to parse DICOM for web browsers
+
+Code Contributors
+=================
+
+I welcome pull requests, please see FAQ below for guidance on this.
+
+* @simonmd - CSS improvements in the cornerstoneDemo application
+* @doncharkowsky - The angle tool in cornerstoneTools
+* @prasath-rasterimages - Touch event bindings in cornerstoneTools
+* @jpamburn - Performance optimizations for signed data, fixes for image caching
+* @jmhmd - for getPixels() implementation
+* @devishree-raster - for flip and rotate implementation
+
+FAQ
+===
+
+_Why did you decide to license this library using the open source MIT license?_
+
+The main reason this library is released as [open source](http://en.wikipedia.org/wiki/Open_source) is
+that I believe that medical imaging in particular can do a lot more to improve patient outcomes
+but the cost of doing so is prohibitive.  Making this library open source removes the cost barrier and will
+hopefully usher in a new set of medical imaging based applications.
+
+The old adage [a picture is worth a thousand words](http://en.wikipedia.org/wiki/A_picture_is_worth_a_thousand_words)
+is very true in medical imaging.  When a patient is going through a disease process, they often face fear
+and confusion.  Medical terminology amplifies these issues as it is hard to understand and therefore
+disempowering.  Medical imaging allows a mysterious health issue to be visualized and therefore brings a
+level of understanding that just can't be accomplished via textual information found in lab or radiology
+reports.  By helping a patient (and its supporting friends/family) connect with the disease visually through
+images, it is believed that fear, anxiety and confusion will all be reduced which
+will increase optimism and therefore patient outcomes.
+
+It is my hope that this library be used to build a variety of applications and experiences
+to deliver on this vision.  The MIT license allows this library to be used in any type of application - personal,
+open source and commercial and is therefore appropriate to support this vision.  If you are reading this,
+I hope you can join me in this mission as there is still a lot to be done.
+
+_Why doesn't Cornerstone natively support the display of DICOM images?_
+
+While DICOM has support for just about every type of medical image, there are many cases where medical images
+are not stored in DICOM format.  In many cases, a PACS may receive DICOM images but store them in a proprietary
+format on disk.  In this case, it can be faster to access images by having an image loader that works with
+a proprietary PACS interface that would not require conversion from the proprietary format into a standard format
+like DICOM.  Another example of this is is dermatology where images are often taken using standard
+digital cameras and are stored as JPEG not DICOM.
+
+The main reason this library is not based around DICOM is that it wants to reach the widest possible adoption
+and that will be accomplished by supporting as many types of image containers and transports possible.
+Another side effect of this approach is that the code base is smaller and easier to understand since
+it is focused on doing exactly one thing.  That being said, it is is expected that the majority of images
+displayed using this library will have originated as DICOM images.  It is therefore important to make sure
+that there are no limitations with respect to displaying the different types of DICOM images and have robust
+supporting libraries for DICOM.  Separate libraries to add DICOM specific support already exist, check out the
+[CornerstoneWADOImageLoader](https://github.com/chafey/cornerstoneWADOImageLoader) library and
+the (dicomParser)[https://github.com/chafey/dicomParser] library.
+
+_Why doesn't Cornerstone include basic tools like ww/wc using the mouse?_
+
+There is no standard for user interaction in medical imaging and a wide variety of interaction paradigms exist.
+For example, one medical imaging application may use the left mouse button to adjust ww/wc and another may use the
+right mouse button.  The main reason this library does not include tools is that it wants to reach the widest possible
+adoption and that will only be accomplished by making any interaction paradigm possible.  No tools
+are therefore provided with this library allowing users of the library to choose
+whatever interaction paradigm they like.  It is also hoped that this approach will make it easier for developers
+to experiment with new user input mechanisms like [Kinect](http://en.wikipedia.org/wiki/Kinect) or
+[Accelerometer](http://en.wikipedia.org/wiki/Accelerometer).  Another side effect of this
+approach is that the code base is smaller and easier to understand since it is focused on doing exactly one
+thing.  Tools are provided using the separate [CornerstoneTools](https://github.com/chafey/cornerstoneTools)
+if desired.
+
+_Why does this library require HTML5 canvas when IE8 is the main browser used in healthcare?_
+
+The fact that IE8 is the most popular commonly used web browser in healthcare right now is a temporary
+situation.  It is expected that 50% of the industry will have HTML5 based web browsers deployed by the end
+of 2015 and 90% by 2017.  The library made a tradeoff to focus on the future platform to keep the code base
+simple and avoid compromises related to older browser technology.  Note that it may be possible to get
+this library to work on IE8 using [excanvas](https://code.google.com/p/explorercanvas/) but I haven't tried
+it yet.
+
+_Why doesn't this library support stacks of images?_
+
+Images stack functionality such as a CT series or MRI series can actually be quite complex.  Regardless of
+what stack functionality is desired, all stacks ultimately need to be able to display a single image and that
+is what this library is focused on doing.  Stack functionality is therefore pushed up to a higher layer.  The
+[CornerstoneTools](https://github.com/chafey/cornerstoneTools) contains stack functionality and is a good place
+to look to see how various stack related functionality is implemented.
+
+_How do you envision this library supporting 3D functionality such as MPR, MIP and VR?_
+
+This library would be responsible for displaying the rendered image to the user.  The rendering of the
+3D image would be done by some other library - perhaps on the server side.  This library is purely 2D and has
+no knowledge of 3D image space.  It will probably make sense to have several layers on top of this library
+to provide 3D functionality.  For example, one layer that has a 3D viewport with properties such as transformation
+matrix, slice thickness, transfer function/LUT, segmentation masks, etc.  And another 3D tools layer that provides
+various tools on top of the 3d viewport (rotate, zoom, segment, scroll, etc).  I do have a working 3D server that
+is integrated with cornerstone but am keeping the code closed for now (this may change in the future - TBD).
+
+_Why did you add jQuery as a dependency?_
+
+Primarily for its custom event handling.
+
+_I would like to contribute code - how do I do this?_
+
+Fork the repository, make your change and submit a pull request.
+
+_Any guidance on submitting changes?_
+
+While I do appreciate code contributions, I will not merge it unless it meets the following criteria:
+
+* Functionality is appropriate for the repository.  Consider posting on the forum if you are not sure
+* Code quality is acceptable.  I don't have coding standards defined, but make sure it passes jshint and looks like
+   the rest of the code in the repository.
+* Quality of design is acceptable.  This is a bit subjective so you should consider posting on the forum for specific guidance
+
+I will provide feedback on your pull request if it fails to meet any of the above.
+
+Please consider separate pull requests for each feature as big pull requests are very time consuming to understand.
+It is highly probably that I will reject a large pull request due to the time it would take to comprehend.
+
+_Will you add feature XYZ for me?_
+
+If it is in the roadmap, I intend to implement it some day - probably when I actually need it.  If you really need
+something now and are willing to pay for it, try posting on the cornerstone platform google group
+
+_How mature is Cornerstone?_
+
+Each repository is at a different level of maturity.  There are at least 50 image viewer projects using Cornerstone
+and the feedback has been consistently strong about the architecture, design and quality.  The cornerstoneTools library
+is the least mature from a framework and breadth of functionality perspective - but the implemented features work well.
+
+Copyright
+=========
+
+Copyright 2015 Chris Hafey [chafey at gmail.com](mailto:chafey at gmail.com)
+
+

Added: trunk/packages/orthanc-webviewer/trunk/debian/JS/cornerstone-0.8.4/cornerstone.css
===================================================================
--- trunk/packages/orthanc-webviewer/trunk/debian/JS/cornerstone-0.8.4/cornerstone.css	                        (rev 0)
+++ trunk/packages/orthanc-webviewer/trunk/debian/JS/cornerstone-0.8.4/cornerstone.css	2015-12-07 15:27:48 UTC (rev 20664)
@@ -0,0 +1,17 @@
+/*! cornerstone - v0.8.4 - 2015-09-12 | (c) 2014 Chris Hafey | https://github.com/chafey/cornerstone */
+.cornerstone-enabled-image {
+
+    /* prevent text selection from occurring when dragging the mouse on the div */
+    /* http://stackoverflow.com/questions/826782/css-rule-to-disable-text-selection-highlighting */
+    -webkit-touch-callout: none;
+    -webkit-user-select: none;
+    -khtml-user-select: none;
+    -moz-user-select: none;
+    -ms-user-select: none;
+    user-select: none;
+
+    /* force the cursor to always be the default arrow.  This prevents it from changing to an ibar when it is
+       over HTML based text overlays (four corners */
+    cursor:default;
+}
+

Added: trunk/packages/orthanc-webviewer/trunk/debian/JS/cornerstone-0.8.4/cornerstone.js
===================================================================
--- trunk/packages/orthanc-webviewer/trunk/debian/JS/cornerstone-0.8.4/cornerstone.js	                        (rev 0)
+++ trunk/packages/orthanc-webviewer/trunk/debian/JS/cornerstone-0.8.4/cornerstone.js	2015-12-07 15:27:48 UTC (rev 20664)
@@ -0,0 +1,2022 @@
+/*! cornerstone - v0.8.4 - 2015-09-12 | (c) 2014 Chris Hafey | https://github.com/chafey/cornerstone */
+if(typeof cornerstone === 'undefined'){
+    cornerstone = {
+        internal : {},
+        rendering: {}
+    };
+}
+
+(function (cornerstone) {
+
+    "use strict";
+
+    function disable(element) {
+        if(element === undefined) {
+            throw "disable: element element must not be undefined";
+        }
+
+        // Search for this element in this list of enabled elements
+        var enabledElements = cornerstone.getEnabledElements();
+        for(var i=0; i < enabledElements.length; i++) {
+            if(enabledElements[i].element === element) {
+                // We found it!
+
+                // Fire an event so dependencies can cleanup
+                var eventData = {
+                    element : element
+                };
+                $(element).trigger("CornerstoneElementDisabled", eventData);
+
+                // remove the child dom elements that we created (e.g.canvas)
+                enabledElements[i].element.removeChild(enabledElements[i].canvas);
+
+                // remove this element from the list of enabled elements
+                enabledElements.splice(i, 1);
+                return;
+            }
+        }
+    }
+
+    // module/private exports
+    cornerstone.disable = disable;
+
+}(cornerstone));
+/**
+ * This module is responsible for enabling an element to display images with cornerstone
+ */
+(function ($, cornerstone) {
+
+    "use strict";
+
+    /**
+     * sets a new image object for a given element
+     * @param element
+     * @param image
+     */
+    function displayImage(element, image, viewport) {
+        if(element === undefined) {
+            throw "displayImage: parameter element cannot be undefined";
+        }
+        if(image === undefined) {
+            throw "displayImage: parameter image cannot be undefined";
+        }
+
+        var enabledElement = cornerstone.getEnabledElement(element);
+
+        enabledElement.image = image;
+
+        if(enabledElement.viewport === undefined) {
+            enabledElement.viewport = cornerstone.internal.getDefaultViewport(enabledElement.canvas, image);
+        }
+
+        // merge viewport
+        if(viewport) {
+            for(var attrname in viewport)
+            {
+                if(viewport[attrname] !== null) {
+                    enabledElement.viewport[attrname] = viewport[attrname];
+                }
+            }
+        }
+
+        var now = new Date();
+        var frameRate;
+        if(enabledElement.lastImageTimeStamp !== undefined) {
+            var timeSinceLastImage = now.getTime() - enabledElement.lastImageTimeStamp;
+            frameRate = (1000 / timeSinceLastImage).toFixed();
+        } else {
+        }
+        enabledElement.lastImageTimeStamp = now.getTime();
+
+        var newImageEventData = {
+            viewport : enabledElement.viewport,
+            element : enabledElement.element,
+            image : enabledElement.image,
+            enabledElement : enabledElement,
+            frameRate : frameRate
+        };
+
+        $(enabledElement.element).trigger("CornerstoneNewImage", newImageEventData);
+
+        cornerstone.updateImage(element);
+    }
+
+    // module/private exports
+    cornerstone.displayImage = displayImage;
+}($, cornerstone));
+/**
+ * This module is responsible for immediately drawing an enabled element
+ */
+
+(function ($, cornerstone) {
+
+    "use strict";
+
+    /**
+     * Immediately draws the enabled element
+     *
+     * @param element
+     */
+    function draw(element) {
+        var enabledElement = cornerstone.getEnabledElement(element);
+
+        if(enabledElement.image === undefined) {
+            throw "draw: image has not been loaded yet";
+        }
+
+        cornerstone.drawImage(enabledElement);
+    }
+
+    // Module exports
+    cornerstone.draw = draw;
+
+}($, cornerstone));
+/**
+ * This module is responsible for drawing invalidated enabled elements
+ */
+
+(function ($, cornerstone) {
+
+    "use strict";
+
+    /**
+     * Draws all invalidated enabled elements and clears the invalid flag after drawing it
+     */
+    function drawInvalidated()
+    {
+        var enabledElements = cornerstone.getEnabledElements();
+        for(var i=0;i < enabledElements.length; i++) {
+            var ee = enabledElements[i];
+            if(ee.invalid === true) {
+                cornerstone.drawImage(ee);
+            }
+        }
+    }
+
+    // Module exports
+    cornerstone.drawInvalidated = drawInvalidated;
+}($, cornerstone));
+/**
+ * This module is responsible for enabling an element to display images with cornerstone
+ */
+(function (cornerstone) {
+
+    "use strict";
+
+    function enable(element) {
+        if(element === undefined) {
+            throw "enable: parameter element cannot be undefined";
+        }
+
+        var canvas = document.createElement('canvas');
+        element.appendChild(canvas);
+
+        var el = {
+            element: element,
+            canvas: canvas,
+            image : undefined, // will be set once image is loaded
+            invalid: false, // true if image needs to be drawn, false if not
+            data : {}
+        };
+        cornerstone.addEnabledElement(el);
+
+        cornerstone.resize(element, true);
+
+        return element;
+    }
+
+    // module/private exports
+    cornerstone.enable = enable;
+}(cornerstone));
+(function (cornerstone) {
+
+    "use strict";
+
+    function getElementData(el, dataType) {
+        var ee = cornerstone.getEnabledElement(el);
+        if(ee.data.hasOwnProperty(dataType) === false)
+        {
+            ee.data[dataType] = {};
+        }
+        return ee.data[dataType];
+    }
+
+    function removeElementData(el, dataType) {
+        var ee = cornerstone.getEnabledElement(el);
+        delete ee.data[dataType];
+    }
+
+    // module/private exports
+    cornerstone.getElementData = getElementData;
+    cornerstone.removeElementData = removeElementData;
+
+}(cornerstone));
+(function (cornerstone) {
+
+    "use strict";
+
+    var enabledElements = [];
+
+    function getEnabledElement(element) {
+        if(element === undefined) {
+            throw "getEnabledElement: parameter element must not be undefined";
+        }
+        for(var i=0; i < enabledElements.length; i++) {
+            if(enabledElements[i].element == element) {
+                return enabledElements[i];
+            }
+        }
+
+        throw "element not enabled";
+    }
+
+    function addEnabledElement(enabledElement) {
+        if(enabledElement === undefined) {
+            throw "getEnabledElement: enabledElement element must not be undefined";
+        }
+
+        enabledElements.push(enabledElement);
+    }
+
+    function getEnabledElementsByImageId(imageId) {
+        var ees = [];
+        enabledElements.forEach(function(enabledElement) {
+            if(enabledElement.image && enabledElement.image.imageId === imageId) {
+                ees.push(enabledElement);
+            }
+        });
+        return ees;
+    }
+
+    function getEnabledElements() {
+        return enabledElements;
+    }
+
+    // module/private exports
+    cornerstone.getEnabledElement = getEnabledElement;
+    cornerstone.addEnabledElement = addEnabledElement;
+    cornerstone.getEnabledElementsByImageId = getEnabledElementsByImageId;
+    cornerstone.getEnabledElements = getEnabledElements;
+}(cornerstone));
+/**
+ * This module will fit an image to fit inside the canvas displaying it such that all pixels
+ * in the image are viewable
+ */
+(function (cornerstone) {
+
+    "use strict";
+
+    function getImageSize(enabledElement) {
+      if(enabledElement.viewport.rotation === 0 ||enabledElement.viewport.rotation === 180) {
+        return {
+          width: enabledElement.image.width,
+          height: enabledElement.image.height
+        };
+      } else {
+        return {
+          width: enabledElement.image.height,
+          height: enabledElement.image.width
+        };
+      }
+    }
+
+    /**
+     * Adjusts an images scale and center so the image is centered and completely visible
+     * @param element
+     */
+    function fitToWindow(element)
+    {
+        var enabledElement = cornerstone.getEnabledElement(element);
+        var imageSize = getImageSize(enabledElement);
+
+        var verticalScale = enabledElement.canvas.height / imageSize.height;
+        var horizontalScale= enabledElement.canvas.width / imageSize.width;
+        if(horizontalScale < verticalScale) {
+          enabledElement.viewport.scale = horizontalScale;
+        }
+        else
+        {
+          enabledElement.viewport.scale = verticalScale;
+        }
+        enabledElement.viewport.translation.x = 0;
+        enabledElement.viewport.translation.y = 0;
+        cornerstone.updateImage(element);
+    }
+
+    cornerstone.fitToWindow = fitToWindow;
+}(cornerstone));
+
+/**
+ * This file is responsible for returning the default viewport for an image
+ */
+
+(function ($, cornerstone) {
+
+    "use strict";
+
+    /**
+     * returns a default viewport for display the specified image on the specified
+     * enabled element.  The default viewport is fit to window
+     *
+     * @param element
+     * @param image
+     */
+    function getDefaultViewportForImage(element, image) {
+        var enabledElement = cornerstone.getEnabledElement(element);
+        var viewport = cornerstone.internal.getDefaultViewport(enabledElement.canvas, image);
+        return viewport;
+    }
+
+    // Module exports
+    cornerstone.getDefaultViewportForImage = getDefaultViewportForImage;
+}($, cornerstone));
+/**
+ * This module is responsible for returning the currently displayed image for an element
+ */
+
+(function ($, cornerstone) {
+
+    "use strict";
+
+    /**
+     * returns the currently displayed image for an element or undefined if no image has
+     * been displayed yet
+     *
+     * @param element
+     */
+    function getImage(element) {
+        var enabledElement = cornerstone.getEnabledElement(element);
+        return enabledElement.image;
+    }
+
+    // Module exports
+    cornerstone.getImage = getImage;
+}($, cornerstone));
+/**
+ * This module returns a subset of the stored pixels of an image
+ */
+(function (cornerstone) {
+
+    "use strict";
+
+    /**
+     * Returns array of pixels with modality LUT transformation applied
+     */
+    function getPixels(element, x, y, width, height) {
+
+        var storedPixels = cornerstone.getStoredPixels(element, x, y, width, height);
+        var ee = cornerstone.getEnabledElement(element);
+
+        var mlutfn = cornerstone.internal.getModalityLUT(ee.image.slope, ee.image.intercept, ee.viewport.modalityLUT);
+
+        var modalityPixels = storedPixels.map(mlutfn);
+
+        return modalityPixels;
+    }
+
+    // module exports
+    cornerstone.getPixels = getPixels;
+}(cornerstone));
+/**
+ * This module returns a subset of the stored pixels of an image
+ */
+(function (cornerstone) {
+
+    "use strict";
+
+    /**
+     * Returns an array of stored pixels given a rectangle in the image
+     * @param element
+     * @param x
+     * @param y
+     * @param width
+     * @param height
+     * @returns {Array}
+     */
+    function getStoredPixels(element, x, y, width, height) {
+        if(element === undefined) {
+            throw "getStoredPixels: parameter element must not be undefined";
+        }
+
+        x = Math.round(x);
+        y = Math.round(y);
+        var ee = cornerstone.getEnabledElement(element);
+        var storedPixels = [];
+        var index = 0;
+        var pixelData = ee.image.getPixelData();
+        for(var row=0; row < height; row++) {
+            for(var column=0; column < width; column++) {
+                var spIndex = ((row + y) * ee.image.columns) + (column + x);
+                storedPixels[index++] = pixelData[spIndex];
+            }
+        }
+        return storedPixels;
+    }
+
+    // module exports
+    cornerstone.getStoredPixels = getStoredPixels;
+}(cornerstone));
+/**
+ * This module contains functions to deal with getting and setting the viewport for an enabled element
+ */
+(function (cornerstone) {
+
+    "use strict";
+
+    /**
+     * Returns the viewport for the specified enabled element
+     * @param element
+     * @returns {*}
+     */
+    function getViewport(element) {
+        var enabledElement = cornerstone.getEnabledElement(element);
+
+        var viewport = enabledElement.viewport;
+        if(viewport === undefined) {
+            return undefined;
+        }
+        return {
+            scale : viewport.scale,
+            translation : {
+                x : viewport.translation.x,
+                y : viewport.translation.y
+            },
+            voi : {
+                windowWidth: viewport.voi.windowWidth,
+                windowCenter : viewport.voi.windowCenter
+            },
+            invert : viewport.invert,
+            pixelReplication: viewport.pixelReplication,
+            rotation: viewport.rotation, 
+            hflip: viewport.hflip,
+            vflip: viewport.vflip,
+            modalityLUT: viewport.modalityLUT,
+            voiLUT: viewport.voiLUT
+        };
+    }
+
+    // module/private exports
+    cornerstone.getViewport = getViewport;
+
+}(cornerstone));
+
+/**
+ * This module deals with caching images
+ */
+
+(function (cornerstone) {
+
+    "use strict";
+
+    var imageCache = {};
+
+    var cachedImages = [];
+
+    var maximumSizeInBytes = 1024 * 1024 * 1024; // 1 GB
+    var cacheSizeInBytes = 0;
+
+    function setMaximumSizeBytes(numBytes) {
+        if (numBytes === undefined) {
+            throw "setMaximumSizeBytes: parameter numBytes must not be undefined";
+        }
+        if (numBytes.toFixed === undefined) {
+            throw "setMaximumSizeBytes: parameter numBytes must be a number";
+        }
+
+        maximumSizeInBytes = numBytes;
+        purgeCacheIfNecessary();
+    }
+
+    function purgeCacheIfNecessary() {
+        // if max cache size has not been exceeded, do nothing
+        if (cacheSizeInBytes <= maximumSizeInBytes) {
+            return;
+        }
+
+        // cache size has been exceeded, create list of images sorted by timeStamp
+        // so we can purge the least recently used image
+        function compare(a,b) {
+            if (a.timeStamp > b.timeStamp) {
+                return -1;
+            }
+            if (a.timeStamp < b.timeStamp) {
+                return 1;
+            }
+            return 0;
+        }
+        cachedImages.sort(compare);
+
+        // remove images as necessary
+        while(cacheSizeInBytes > maximumSizeInBytes) {
+            var lastCachedImage = cachedImages[cachedImages.length - 1];
+            cacheSizeInBytes -= lastCachedImage.sizeInBytes;
+            delete imageCache[lastCachedImage.imageId];
+            lastCachedImage.imagePromise.reject();
+            cachedImages.pop();
+            $(cornerstone).trigger('CornerstoneImageCachePromiseRemoved', {imageId: lastCachedImage.imageId});
+        }
+
+        var cacheInfo = cornerstone.imageCache.getCacheInfo();
+        $(cornerstone).trigger('CornerstoneImageCacheFull', cacheInfo);
+    }
+
+    function putImagePromise(imageId, imagePromise) {
+        if (imageId === undefined) {
+            throw "getImagePromise: imageId must not be undefined";
+        }
+        if (imagePromise === undefined) {
+            throw "getImagePromise: imagePromise must not be undefined";
+        }
+
+        if (imageCache.hasOwnProperty(imageId) === true) {
+            throw "putImagePromise: imageId already in cache";
+        }
+
+        var cachedImage = {
+            loaded : false,
+            imageId : imageId,
+            imagePromise : imagePromise,
+            timeStamp : new Date(),
+            sizeInBytes: 0
+        };
+
+        imageCache[imageId] = cachedImage;
+        cachedImages.push(cachedImage);
+
+        imagePromise.then(function(image) {
+            cachedImage.loaded = true;
+
+            if (image.sizeInBytes === undefined) {
+                throw "putImagePromise: image does not have sizeInBytes property or";
+            }
+            if (image.sizeInBytes.toFixed === undefined) {
+                throw "putImagePromise: image.sizeInBytes is not a number";
+            }
+            cachedImage.sizeInBytes = image.sizeInBytes;
+            cacheSizeInBytes += cachedImage.sizeInBytes;
+            purgeCacheIfNecessary();
+        });
+    }
+
+    function getImagePromise(imageId) {
+        if (imageId === undefined) {
+            throw "getImagePromise: imageId must not be undefined";
+        }
+        var cachedImage = imageCache[imageId];
+        if (cachedImage === undefined) {
+            return undefined;
+        }
+
+        // bump time stamp for cached image
+        cachedImage.timeStamp = new Date();
+        return cachedImage.imagePromise;
+    }
+
+    function removeImagePromise(imageId) {
+        if (imageId === undefined) {
+            throw "removeImagePromise: imageId must not be undefined";
+        }
+        var cachedImage = imageCache[imageId];
+        if (cachedImage === undefined) {
+            throw "removeImagePromise: imageId must not be undefined";
+        }
+        cachedImages.splice( cachedImages.indexOf(cachedImage), 1);
+        cacheSizeInBytes -= cachedImage.sizeInBytes;
+        delete imageCache[imageId];
+
+        return cachedImage.imagePromise;
+    }
+
+    function getCacheInfo() {
+        return {
+            maximumSizeInBytes : maximumSizeInBytes,
+            cacheSizeInBytes : cacheSizeInBytes,
+            numberOfImagesCached: cachedImages.length
+        };
+    }
+
+    function purgeCache() {
+        while (cachedImages.length > 0) {
+            var removedCachedImage = cachedImages.pop();
+            delete imageCache[removedCachedImage.imageId];
+            removedCachedImage.imagePromise.reject();
+        }
+        cacheSizeInBytes = 0;
+    }
+
+    // module exports
+    cornerstone.imageCache = {
+        putImagePromise : putImagePromise,
+        getImagePromise: getImagePromise,
+        removeImagePromise: removeImagePromise,
+        setMaximumSizeBytes: setMaximumSizeBytes,
+        getCacheInfo : getCacheInfo,
+        purgeCache: purgeCache,
+        cachedImages: cachedImages
+    };
+
+}(cornerstone));
+
+/**
+ * This module deals with ImageLoaders, loading images and caching images
+ */
+
+(function ($, cornerstone) {
+
+    "use strict";
+
+    var imageLoaders = {};
+
+    var unknownImageLoader;
+
+    function loadImageFromImageLoader(imageId) {
+        var colonIndex = imageId.indexOf(":");
+        var scheme = imageId.substring(0, colonIndex);
+        var loader = imageLoaders[scheme];
+        var imagePromise;
+        if(loader === undefined || loader === null) {
+            if(unknownImageLoader !== undefined) {
+                imagePromise = unknownImageLoader(imageId);
+                return imagePromise;
+            }
+            else {
+                return undefined;
+            }
+        }
+        imagePromise = loader(imageId);
+
+        // broadcast an image loaded event once the image is loaded
+        // This is based on the idea here: http://stackoverflow.com/questions/3279809/global-custom-events-in-jquery
+        imagePromise.then(function(image) {
+            $(cornerstone).trigger('CornerstoneImageLoaded', {image: image});
+        });
+
+        return imagePromise;
+    }
+
+    // Loads an image given an imageId and returns a promise which will resolve
+    // to the loaded image object or fail if an error occurred.  The loaded image
+    // is not stored in the cache
+    function loadImage(imageId) {
+        if(imageId === undefined) {
+            throw "loadImage: parameter imageId must not be undefined";
+        }
+
+        var imagePromise = cornerstone.imageCache.getImagePromise(imageId);
+        if(imagePromise !== undefined) {
+            return imagePromise;
+        }
+
+        imagePromise = loadImageFromImageLoader(imageId);
+        if(imagePromise === undefined) {
+            throw "loadImage: no image loader for imageId";
+        }
+
+        return imagePromise;
+    }
+
+    // Loads an image given an imageId and returns a promise which will resolve
+    // to the loaded image object or fail if an error occurred.  The image is
+    // stored in the cache
+    function loadAndCacheImage(imageId) {
+        if(imageId === undefined) {
+            throw "loadAndCacheImage: parameter imageId must not be undefined";
+        }
+
+        var imagePromise = cornerstone.imageCache.getImagePromise(imageId);
+        if(imagePromise !== undefined) {
+            return imagePromise;
+        }
+
+        imagePromise = loadImageFromImageLoader(imageId);
+        if(imagePromise === undefined) {
+            throw "loadAndCacheImage: no image loader for imageId";
+        }
+
+        cornerstone.imageCache.putImagePromise(imageId, imagePromise);
+
+        return imagePromise;
+    }
+
+
+    // registers an imageLoader plugin with cornerstone for the specified scheme
+    function registerImageLoader(scheme, imageLoader) {
+        imageLoaders[scheme] = imageLoader;
+    }
+
+    // Registers a new unknownImageLoader and returns the previous one (if it exists)
+    function registerUnknownImageLoader(imageLoader) {
+        var oldImageLoader = unknownImageLoader;
+        unknownImageLoader = imageLoader;
+        return oldImageLoader;
+    }
+
+    // module exports
+
+    cornerstone.loadImage = loadImage;
+    cornerstone.loadAndCacheImage = loadAndCacheImage;
+    cornerstone.registerImageLoader = registerImageLoader;
+    cornerstone.registerUnknownImageLoader = registerUnknownImageLoader;
+
+}($, cornerstone));
+
+(function (cornerstone) {
+
+    "use strict";
+
+    function calculateTransform(enabledElement, scale) {
+
+        var transform = new cornerstone.internal.Transform();
+        transform.translate(enabledElement.canvas.width/2, enabledElement.canvas.height / 2);
+
+        //Apply the rotation before scaling for non square pixels
+        var angle = enabledElement.viewport.rotation;
+        if(angle!==0) {
+            transform.rotate(angle*Math.PI/180);
+        }
+
+        // apply the scale
+        var widthScale = enabledElement.viewport.scale;
+        var heightScale = enabledElement.viewport.scale;
+        if(enabledElement.image.rowPixelSpacing < enabledElement.image.columnPixelSpacing) {
+            widthScale = widthScale * (enabledElement.image.columnPixelSpacing / enabledElement.image.rowPixelSpacing);
+        }
+        else if(enabledElement.image.columnPixelSpacing < enabledElement.image.rowPixelSpacing) {
+            heightScale = heightScale * (enabledElement.image.rowPixelSpacing / enabledElement.image.columnPixelSpacing);
+        }
+        transform.scale(widthScale, heightScale);
+
+        // unrotate to so we can translate unrotated
+        if(angle!==0) {
+            transform.rotate(-angle*Math.PI/180);
+        }
+
+        // apply the pan offset
+        transform.translate(enabledElement.viewport.translation.x, enabledElement.viewport.translation.y);
+
+        // rotate again so we can apply general scale
+        if(angle!==0) {
+            transform.rotate(angle*Math.PI/180);
+        }
+
+        if(scale !== undefined) {
+            // apply the font scale
+            transform.scale(scale, scale);
+        }
+
+        //Apply Flip if required
+        if(enabledElement.viewport.hflip) {
+            transform.scale(-1,1);
+        }
+
+        if(enabledElement.viewport.vflip) {
+            transform.scale(1,-1);
+        }
+
+        // translate the origin back to the corner of the image so the event handlers can draw in image coordinate system
+        transform.translate(-enabledElement.image.width / 2 , -enabledElement.image.height/ 2);
+        return transform;
+    }
+
+    // Module exports
+    cornerstone.internal.calculateTransform = calculateTransform;
+}(cornerstone));
+/**
+ * This module is responsible for drawing an image to an enabled elements canvas element
+ */
+
+(function ($, cornerstone) {
+
+    "use strict";
+
+    /**
+     * Internal API function to draw an image to a given enabled element
+     * @param enabledElement
+     * @param invalidated - true if pixel data has been invalidated and cached rendering should not be used
+     */
+    function drawImage(enabledElement, invalidated) {
+
+        var start = new Date();
+
+        enabledElement.image.render(enabledElement, invalidated);
+
+        var context = enabledElement.canvas.getContext('2d');
+
+        var end = new Date();
+        var diff = end - start;
+        //console.log(diff + ' ms');
+
+        var eventData = {
+            viewport : enabledElement.viewport,
+            element : enabledElement.element,
+            image : enabledElement.image,
+            enabledElement : enabledElement,
+            canvasContext: context,
+            renderTimeInMs : diff
+        };
+
+        $(enabledElement.element).trigger("CornerstoneImageRendered", eventData);
+        enabledElement.invalid = false;
+    }
+
+    // Module exports
+    cornerstone.internal.drawImage = drawImage;
+    cornerstone.drawImage = drawImage;
+
+}($, cornerstone));
+/**
+ * This module generates a lut for an image
+ */
+
+(function (cornerstone) {
+
+  "use strict";
+
+  function generateLutNew(image, windowWidth, windowCenter, invert, modalityLUT, voiLUT)
+  {
+    if(image.lut === undefined) {
+      image.lut =  new Int16Array(image.maxPixelValue - Math.min(image.minPixelValue,0)+1);
+    }
+    var lut = image.lut;
+    var maxPixelValue = image.maxPixelValue;
+    var minPixelValue = image.minPixelValue;
+
+    var mlutfn = cornerstone.internal.getModalityLUT(image.slope, image.intercept, modalityLUT);
+    var vlutfn = cornerstone.internal.getVOILUT(windowWidth, windowCenter, voiLUT);
+
+    var offset = 0;
+    if(minPixelValue < 0) {
+      offset = minPixelValue;
+    }
+    var storedValue;
+    var modalityLutValue;
+    var voiLutValue;
+    var clampedValue;
+
+    for(storedValue = image.minPixelValue; storedValue <= maxPixelValue; storedValue++)
+    {
+      modalityLutValue = mlutfn(storedValue);
+      voiLutValue = vlutfn(modalityLutValue);
+      clampedValue = Math.min(Math.max(voiLutValue, 0), 255);
+      if(!invert) {
+        lut[storedValue+ (-offset)] = Math.round(clampedValue);
+      } else {
+        lut[storedValue + (-offset)] = Math.round(255 - clampedValue);
+      }
+    }
+    return lut;
+  }
+
+
+
+  /**
+   * Creates a LUT used while rendering to convert stored pixel values to
+   * display pixels
+   *
+   * @param image
+   * @returns {Array}
+   */
+  function generateLut(image, windowWidth, windowCenter, invert, modalityLUT, voiLUT)
+  {
+    if(modalityLUT || voiLUT) {
+      return generateLutNew(image, windowWidth, windowCenter, invert, modalityLUT, voiLUT);
+    }
+
+    if(image.lut === undefined) {
+      image.lut =  new Int16Array(image.maxPixelValue - Math.min(image.minPixelValue,0)+1);
+    }
+    var lut = image.lut;
+
+    var maxPixelValue = image.maxPixelValue;
+    var minPixelValue = image.minPixelValue;
+    var slope = image.slope;
+    var intercept = image.intercept;
+    var localWindowWidth = windowWidth;
+    var localWindowCenter = windowCenter;
+    var modalityLutValue;
+    var voiLutValue;
+    var clampedValue;
+    var storedValue;
+
+    // NOTE: As of Nov 2014, most javascript engines have lower performance when indexing negative indexes.
+    // We improve performance by offsetting the pixel values for signed data to avoid negative indexes
+    // when generating the lut and then undo it in storedPixelDataToCanvasImagedata.  Thanks to @jpambrun
+    // for this contribution!
+
+    var offset = 0;
+    if(minPixelValue < 0) {
+      offset = minPixelValue;
+    }
+
+    if(invert === true) {
+      for(storedValue = image.minPixelValue; storedValue <= maxPixelValue; storedValue++)
+      {
+        modalityLutValue =  storedValue * slope + intercept;
+        voiLutValue = (((modalityLutValue - (localWindowCenter)) / (localWindowWidth) + 0.5) * 255.0);
+        clampedValue = Math.min(Math.max(voiLutValue, 0), 255);
+        lut[storedValue + (-offset)] = Math.round(255 - clampedValue);
+      }
+    }
+    else {
+      for(storedValue = image.minPixelValue; storedValue <= maxPixelValue; storedValue++)
+      {
+        modalityLutValue = storedValue * slope + intercept;
+        voiLutValue = (((modalityLutValue - (localWindowCenter)) / (localWindowWidth) + 0.5) * 255.0);
+        clampedValue = Math.min(Math.max(voiLutValue, 0), 255);
+        lut[storedValue+ (-offset)] = Math.round(clampedValue);
+      }
+    }
+  }
+
+
+  // Module exports
+  cornerstone.internal.generateLutNew = generateLutNew;
+  cornerstone.internal.generateLut = generateLut;
+  cornerstone.generateLutNew = generateLutNew;
+  cornerstone.generateLut = generateLut;
+}(cornerstone));
+
+/**
+ * This module contains a function to get a default viewport for an image given
+ * a canvas element to display it in
+ *
+ */
+(function (cornerstone) {
+
+    "use strict";
+
+    /**
+     * Creates a new viewport object containing default values for the image and canvas
+     * @param canvas
+     * @param image
+     * @returns viewport object
+     */
+    function getDefaultViewport(canvas, image) {
+        if(canvas === undefined) {
+            throw "getDefaultViewport: parameter canvas must not be undefined";
+        }
+        if(image === undefined) {
+            throw "getDefaultViewport: parameter image must not be undefined";
+        }
+        var viewport = {
+            scale : 1.0,
+            translation : {
+                x : 0,
+                y : 0
+            },
+            voi : {
+                windowWidth: image.windowWidth,
+                windowCenter: image.windowCenter,
+            },
+            invert: image.invert,
+            pixelReplication: false,
+            rotation: 0,
+            hflip: false,
+            vflip: false,
+            modalityLUT: image.modalityLUT,
+            voiLUT: image.voiLUT
+        };
+
+        // fit image to window
+        var verticalScale = canvas.height / image.rows;
+        var horizontalScale= canvas.width / image.columns;
+        if(horizontalScale < verticalScale) {
+            viewport.scale = horizontalScale;
+        }
+        else {
+            viewport.scale = verticalScale;
+        }
+        return viewport;
+    }
+
+    // module/private exports
+    cornerstone.internal.getDefaultViewport = getDefaultViewport;
+    cornerstone.getDefaultViewport = getDefaultViewport;
+}(cornerstone));
+
+(function (cornerstone) {
+
+    "use strict";
+
+    function getTransform(enabledElement)
+    {
+        // For now we will calculate it every time it is requested.  In the future, we may want to cache
+        // it in the enabled element to speed things up
+        var transform = cornerstone.internal.calculateTransform(enabledElement);
+        return transform;
+    }
+
+    // Module exports
+    cornerstone.internal.getTransform = getTransform;
+
+}(cornerstone));
+/**
+ * This module is responsible for drawing an image to an enabled elements canvas element
+ */
+
+(function ($, cornerstone) {
+
+    "use strict";
+
+    cornerstone.drawImage = cornerstone.internal.drawImage;
+    cornerstone.generateLut = cornerstone.internal.generateLut;
+    cornerstone.storedPixelDataToCanvasImageData = cornerstone.internal.storedPixelDataToCanvasImageData;
+    cornerstone.storedColorPixelDataToCanvasImageData = cornerstone.internal.storedColorPixelDataToCanvasImageData;
+
+}($, cornerstone));
+/**
+ * This module generates a Modality LUT
+ */
+
+(function (cornerstone) {
+
+  "use strict";
+
+
+  function generateLinearModalityLUT(slope, intercept) {
+    var localSlope = slope;
+    var localIntercept = intercept;
+    return function(sp) {
+      return sp * localSlope + localIntercept;
+    }
+  }
+
+  function generateNonLinearModalityLUT(modalityLUT) {
+    var minValue = modalityLUT.lut[0];
+    var maxValue = modalityLUT.lut[modalityLUT.lut.length -1];
+    var maxValueMapped = modalityLUT.firstValueMapped + modalityLUT.lut.length;
+    return function(sp) {
+      if(sp < modalityLUT.firstValueMapped) {
+        return minValue;
+      }
+      else if(sp >= maxValueMapped)
+      {
+        return maxValue;
+      }
+      else
+      {
+        return modalityLUT.lut[sp];
+      }
+    }
+  }
+
+  function getModalityLUT(slope, intercept, modalityLUT) {
+    if (modalityLUT) {
+      return generateNonLinearModalityLUT(modalityLUT);
+    } else {
+      return generateLinearModalityLUT(slope, intercept);
+    }
+  }
+
+    // Module exports
+    cornerstone.internal.getModalityLUT = getModalityLUT;
+
+}(cornerstone));
+
+/**
+ * This module contains a function to convert stored pixel values to display pixel values using a LUT
+ */
+(function (cornerstone) {
+
+    "use strict";
+
+    function storedColorPixelDataToCanvasImageData(image, lut, canvasImageDataData)
+    {
+        var minPixelValue = image.minPixelValue;
+        var canvasImageDataIndex = 0;
+        var storedPixelDataIndex = 0;
+        var numPixels = image.width * image.height * 4;
+        var storedPixelData = image.getPixelData();
+        var localLut = lut;
+        var localCanvasImageDataData = canvasImageDataData;
+        // NOTE: As of Nov 2014, most javascript engines have lower performance when indexing negative indexes.
+        // We have a special code path for this case that improves performance.  Thanks to @jpambrun for this enhancement
+        if(minPixelValue < 0){
+            while(storedPixelDataIndex < numPixels) {
+                localCanvasImageDataData[canvasImageDataIndex++] = localLut[storedPixelData[storedPixelDataIndex++] + (-minPixelValue)]; // red
+                localCanvasImageDataData[canvasImageDataIndex++] = localLut[storedPixelData[storedPixelDataIndex++] + (-minPixelValue)]; // green
+                localCanvasImageDataData[canvasImageDataIndex] = localLut[storedPixelData[storedPixelDataIndex] + (-minPixelValue)]; // blue
+                storedPixelDataIndex+=2;
+                canvasImageDataIndex+=2;
+            }
+        }else{
+            while(storedPixelDataIndex < numPixels) {
+                localCanvasImageDataData[canvasImageDataIndex++] = localLut[storedPixelData[storedPixelDataIndex++]]; // red
+                localCanvasImageDataData[canvasImageDataIndex++] = localLut[storedPixelData[storedPixelDataIndex++]]; // green
+                localCanvasImageDataData[canvasImageDataIndex] = localLut[storedPixelData[storedPixelDataIndex]]; // blue
+                storedPixelDataIndex+=2;
+                canvasImageDataIndex+=2;
+            }
+        }
+    }
+
+    // Module exports
+    cornerstone.internal.storedColorPixelDataToCanvasImageData = storedColorPixelDataToCanvasImageData;
+    cornerstone.storedColorPixelDataToCanvasImageData = storedColorPixelDataToCanvasImageData;
+
+}(cornerstone));
+
+/**
+ * This module contains a function to convert stored pixel values to display pixel values using a LUT
+ */
+(function (cornerstone) {
+
+    "use strict";
+
+    /**
+     * This function transforms stored pixel values into a canvas image data buffer
+     * by using a LUT.  This is the most performance sensitive code in cornerstone and
+     * we use a special trick to make this go as fast as possible.  Specifically we
+     * use the alpha channel only to control the luminance rather than the red, green and
+     * blue channels which makes it over 3x faster.  The canvasImageDataData buffer needs
+     * to be previously filled with white pixels.
+     *
+     * NOTE: Attribution would be appreciated if you use this technique!
+     *
+     * @param pixelData the pixel data
+     * @param lut the lut
+     * @param canvasImageDataData a canvasImgageData.data buffer filled with white pixels
+     */
+    function storedPixelDataToCanvasImageData(image, lut, canvasImageDataData)
+    {
+        var pixelData = image.getPixelData();
+        var minPixelValue = image.minPixelValue;
+        var canvasImageDataIndex = 3;
+        var storedPixelDataIndex = 0;
+        var localNumPixels = pixelData.length;
+        var localPixelData = pixelData;
+        var localLut = lut;
+        var localCanvasImageDataData = canvasImageDataData;
+        // NOTE: As of Nov 2014, most javascript engines have lower performance when indexing negative indexes.
+        // We have a special code path for this case that improves performance.  Thanks to @jpambrun for this enhancement
+        if(minPixelValue < 0){
+            while(storedPixelDataIndex < localNumPixels) {
+                localCanvasImageDataData[canvasImageDataIndex] = localLut[localPixelData[storedPixelDataIndex++] + (-minPixelValue)]; // alpha
+                canvasImageDataIndex += 4;
+            }
+        }else{
+            while(storedPixelDataIndex < localNumPixels) {
+                localCanvasImageDataData[canvasImageDataIndex] = localLut[localPixelData[storedPixelDataIndex++]]; // alpha
+                canvasImageDataIndex += 4;
+            }
+        }
+    }
+
+    // Module exports
+    cornerstone.internal.storedPixelDataToCanvasImageData = storedPixelDataToCanvasImageData;
+    cornerstone.storedPixelDataToCanvasImageData = storedPixelDataToCanvasImageData;
+
+}(cornerstone));
+
+// Last updated November 2011
+// By Simon Sarris
+// www.simonsarris.com
+// sarris at acm.org
+//
+// Free to use and distribute at will
+// So long as you are nice to people, etc
+
+// Simple class for keeping track of the current transformation matrix
+
+// For instance:
+//    var t = new Transform();
+//    t.rotate(5);
+//    var m = t.m;
+//    ctx.setTransform(m[0], m[1], m[2], m[3], m[4], m[5]);
+
+// Is equivalent to:
+//    ctx.rotate(5);
+
+// But now you can retrieve it :)
+
+(function (cornerstone) {
+
+    "use strict";
+
+
+    // Remember that this does not account for any CSS transforms applied to the canvas
+    function Transform() {
+        this.reset();
+    }
+
+    Transform.prototype.reset = function() {
+        this.m = [1,0,0,1,0,0];
+    };
+
+    Transform.prototype.clone = function() {
+        var transform = new Transform();
+        transform.m[0] = this.m[0];
+        transform.m[1] = this.m[1];
+        transform.m[2] = this.m[2];
+        transform.m[3] = this.m[3];
+        transform.m[4] = this.m[4];
+        transform.m[5] = this.m[5];
+        return transform;
+    };
+
+
+    Transform.prototype.multiply = function(matrix) {
+        var m11 = this.m[0] * matrix.m[0] + this.m[2] * matrix.m[1];
+        var m12 = this.m[1] * matrix.m[0] + this.m[3] * matrix.m[1];
+
+        var m21 = this.m[0] * matrix.m[2] + this.m[2] * matrix.m[3];
+        var m22 = this.m[1] * matrix.m[2] + this.m[3] * matrix.m[3];
+
+        var dx = this.m[0] * matrix.m[4] + this.m[2] * matrix.m[5] + this.m[4];
+        var dy = this.m[1] * matrix.m[4] + this.m[3] * matrix.m[5] + this.m[5];
+
+        this.m[0] = m11;
+        this.m[1] = m12;
+        this.m[2] = m21;
+        this.m[3] = m22;
+        this.m[4] = dx;
+        this.m[5] = dy;
+    };
+
+    Transform.prototype.invert = function() {
+        var d = 1 / (this.m[0] * this.m[3] - this.m[1] * this.m[2]);
+        var m0 = this.m[3] * d;
+        var m1 = -this.m[1] * d;
+        var m2 = -this.m[2] * d;
+        var m3 = this.m[0] * d;
+        var m4 = d * (this.m[2] * this.m[5] - this.m[3] * this.m[4]);
+        var m5 = d * (this.m[1] * this.m[4] - this.m[0] * this.m[5]);
+        this.m[0] = m0;
+        this.m[1] = m1;
+        this.m[2] = m2;
+        this.m[3] = m3;
+        this.m[4] = m4;
+        this.m[5] = m5;
+    };
+
+    Transform.prototype.rotate = function(rad) {
+        var c = Math.cos(rad);
+        var s = Math.sin(rad);
+        var m11 = this.m[0] * c + this.m[2] * s;
+        var m12 = this.m[1] * c + this.m[3] * s;
+        var m21 = this.m[0] * -s + this.m[2] * c;
+        var m22 = this.m[1] * -s + this.m[3] * c;
+        this.m[0] = m11;
+        this.m[1] = m12;
+        this.m[2] = m21;
+        this.m[3] = m22;
+    };
+
+    Transform.prototype.translate = function(x, y) {
+        this.m[4] += this.m[0] * x + this.m[2] * y;
+        this.m[5] += this.m[1] * x + this.m[3] * y;
+    };
+
+    Transform.prototype.scale = function(sx, sy) {
+        this.m[0] *= sx;
+        this.m[1] *= sx;
+        this.m[2] *= sy;
+        this.m[3] *= sy;
+    };
+
+    Transform.prototype.transformPoint = function(px, py) {
+        var x = px;
+        var y = py;
+        px = x * this.m[0] + y * this.m[2] + this.m[4];
+        py = x * this.m[1] + y * this.m[3] + this.m[5];
+        return {x: px, y: py};
+    };
+
+    cornerstone.internal.Transform = Transform;
+}(cornerstone));
+/**
+ * This module generates a VOI LUT
+ */
+
+(function (cornerstone) {
+
+  "use strict";
+
+  function generateLinearVOILUT(windowWidth, windowCenter) {
+    return function(modalityLutValue) {
+      return (((modalityLutValue - (windowCenter)) / (windowWidth) + 0.5) * 255.0);
+    }
+  }
+
+  function generateNonLinearVOILUT(voiLUT) {
+    var shift = voiLUT.numBitsPerEntry - 8;
+    var minValue = voiLUT.lut[0] >> shift;
+    var maxValue = voiLUT.lut[voiLUT.lut.length -1] >> shift;
+    var maxValueMapped = voiLUT.firstValueMapped + voiLUT.lut.length - 1;
+    return function(modalityLutValue) {
+      if(modalityLutValue < voiLUT.firstValueMapped) {
+        return minValue;
+      }
+      else if(modalityLutValue >= maxValueMapped)
+      {
+        return maxValue;
+      }
+      else
+      {
+        return voiLUT.lut[modalityLutValue - voiLUT.firstValueMapped] >> shift;
+      }
+    }
+  }
+
+  function getVOILUT(windowWidth, windowCenter, voiLUT) {
+    if(voiLUT) {
+      return generateNonLinearVOILUT(voiLUT);
+    } else {
+      return generateLinearVOILUT(windowWidth, windowCenter);
+    }
+  }
+
+  // Module exports
+  cornerstone.internal.getVOILUT = getVOILUT;
+}(cornerstone));
+
+/**
+ * This module contains a function to make an image is invalid
+ */
+(function (cornerstone) {
+
+    "use strict";
+
+    /**
+     * Sets the invalid flag on the enabled element and fire an event
+     * @param element
+     */
+    function invalidate(element) {
+        var enabledElement = cornerstone.getEnabledElement(element);
+        enabledElement.invalid = true;
+        var eventData = {
+            element: element
+        };
+        $(enabledElement.element).trigger("CornerstoneInvalidated", eventData);
+    }
+
+    // module exports
+    cornerstone.invalidate = invalidate;
+}(cornerstone));
+/**
+ * This module contains a function to immediately invalidate an image
+ */
+(function (cornerstone) {
+
+    "use strict";
+
+    /**
+     * Forces the image to be updated/redrawn for the specified enabled element
+     * @param element
+     */
+    function invalidateImageId(imageId) {
+
+        var enabledElements = cornerstone.getEnabledElementsByImageId(imageId);
+        enabledElements.forEach(function(enabledElement) {
+            cornerstone.drawImage(enabledElement, true);
+        });
+    }
+
+    // module exports
+    cornerstone.invalidateImageId = invalidateImageId;
+}(cornerstone));
+/**
+ * This module contains a helper function to covert page coordinates to pixel coordinates
+ */
+(function (cornerstone) {
+
+    "use strict";
+
+    /**
+     * Converts a point in the page coordinate system to the pixel coordinate
+     * system
+     * @param element
+     * @param pageX
+     * @param pageY
+     * @returns {{x: number, y: number}}
+     */
+    function pageToPixel(element, pageX, pageY) {
+        var enabledElement = cornerstone.getEnabledElement(element);
+
+        if(enabledElement.image === undefined) {
+            throw "image has not been loaded yet";
+        }
+
+        var image = enabledElement.image;
+
+        // convert the pageX and pageY to the canvas client coordinates
+        var rect = element.getBoundingClientRect();
+        var clientX = pageX - rect.left - window.pageXOffset;
+        var clientY = pageY - rect.top - window.pageYOffset;
+
+        var pt = {x: clientX, y: clientY};
+        var transform = cornerstone.internal.getTransform(enabledElement);
+        transform.invert();
+        return transform.transformPoint(pt.x, pt.y);
+    }
+
+    // module/private exports
+    cornerstone.pageToPixel = pageToPixel;
+
+}(cornerstone));
+
+(function (cornerstone) {
+
+    "use strict";
+
+    /**
+     * Converts a point in the pixel coordinate system to the canvas coordinate system
+     * system.  This can be used to render using canvas context without having the weird
+     * side effects that come from scaling and non square pixels
+     * @param element
+     * @param pt
+     * @returns {x: number, y: number}
+     */
+    function pixelToCanvas(element, pt) {
+        var enabledElement = cornerstone.getEnabledElement(element);
+        var transform = cornerstone.internal.getTransform(enabledElement);
+        return transform.transformPoint(pt.x, pt.y);
+    }
+
+    // module/private exports
+    cornerstone.pixelToCanvas = pixelToCanvas;
+
+}(cornerstone));
+
+/**
+ * This module is responsible for drawing an image to an enabled elements canvas element
+ */
+
+(function (cornerstone) {
+
+    "use strict";
+
+    var colorRenderCanvas = document.createElement('canvas');
+    var colorRenderCanvasContext;
+    var colorRenderCanvasData;
+
+    var lastRenderedImageId;
+    var lastRenderedViewport = {};
+
+    function initializeColorRenderCanvas(image)
+    {
+        // Resize the canvas
+        colorRenderCanvas.width = image.width;
+        colorRenderCanvas.height = image.height;
+
+        // get the canvas data so we can write to it directly
+        colorRenderCanvasContext = colorRenderCanvas.getContext('2d');
+        colorRenderCanvasContext.fillStyle = 'white';
+        colorRenderCanvasContext.fillRect(0,0, colorRenderCanvas.width, colorRenderCanvas.height);
+        colorRenderCanvasData = colorRenderCanvasContext.getImageData(0,0,image.width, image.height);
+    }
+
+
+    function getLut(image, viewport)
+    {
+        // if we have a cached lut and it has the right values, return it immediately
+        if(image.lut !== undefined &&
+            image.lut.windowCenter === viewport.voi.windowCenter &&
+            image.lut.windowWidth === viewport.voi.windowWidth &&
+            image.lut.invert === viewport.invert) {
+            return image.lut;
+        }
+
+        // lut is invalid or not present, regenerate it and cache it
+        cornerstone.generateLut(image, viewport.voi.windowWidth, viewport.voi.windowCenter, viewport.invert);
+        image.lut.windowWidth = viewport.voi.windowWidth;
+        image.lut.windowCenter = viewport.voi.windowCenter;
+        image.lut.invert = viewport.invert;
+        return image.lut;
+    }
+
+    function doesImageNeedToBeRendered(enabledElement, image)
+    {
+        if(image.imageId !== lastRenderedImageId ||
+            lastRenderedViewport.windowCenter !== enabledElement.viewport.voi.windowCenter ||
+            lastRenderedViewport.windowWidth !== enabledElement.viewport.voi.windowWidth ||
+            lastRenderedViewport.invert !== enabledElement.viewport.invert ||
+            lastRenderedViewport.rotation !== enabledElement.viewport.rotation ||  
+            lastRenderedViewport.hflip !== enabledElement.viewport.hflip ||
+            lastRenderedViewport.vflip !== enabledElement.viewport.vflip
+            )
+        {
+            return true;
+        }
+
+        return false;
+    }
+
+    function getRenderCanvas(enabledElement, image, invalidated)
+    {
+        // apply the lut to the stored pixel data onto the render canvas
+
+        if(enabledElement.viewport.voi.windowWidth === enabledElement.image.windowWidth &&
+            enabledElement.viewport.voi.windowCenter === enabledElement.image.windowCenter &&
+            enabledElement.viewport.invert === false)
+        {
+            // the color image voi/invert has not been modified, request the canvas that contains
+            // it so we can draw it directly to the display canvas
+            return image.getCanvas();
+        }
+        else
+        {
+            if(doesImageNeedToBeRendered(enabledElement, image) === false && invalidated !== true) {
+                return colorRenderCanvas;
+            }
+
+            // If our render canvas does not match the size of this image reset it
+            // NOTE: This might be inefficient if we are updating multiple images of different
+            // sizes frequently.
+            if(colorRenderCanvas.width !== image.width || colorRenderCanvas.height != image.height) {
+                initializeColorRenderCanvas(image);
+            }
+
+            // get the lut to use
+            var colorLut = getLut(image, enabledElement.viewport);
+
+            // the color image voi/invert has been modified - apply the lut to the underlying
+            // pixel data and put it into the renderCanvas
+            cornerstone.storedColorPixelDataToCanvasImageData(image, colorLut, colorRenderCanvasData.data);
+            colorRenderCanvasContext.putImageData(colorRenderCanvasData, 0, 0);
+            return colorRenderCanvas;
+        }
+    }
+
+    /**
+     * API function to render a color image to an enabled element
+     * @param enabledElement
+     * @param invalidated - true if pixel data has been invaldiated and cached rendering should not be used
+     */
+    function renderColorImage(enabledElement, invalidated) {
+
+        if(enabledElement === undefined) {
+            throw "drawImage: enabledElement parameter must not be undefined";
+        }
+        var image = enabledElement.image;
+        if(image === undefined) {
+            throw "drawImage: image must be loaded before it can be drawn";
+        }
+
+        // get the canvas context and reset the transform
+        var context = enabledElement.canvas.getContext('2d');
+        context.setTransform(1, 0, 0, 1, 0, 0);
+
+        // clear the canvas
+        context.fillStyle = 'black';
+        context.fillRect(0,0, enabledElement.canvas.width, enabledElement.canvas.height);
+
+        // turn off image smooth/interpolation if pixelReplication is set in the viewport
+        if(enabledElement.viewport.pixelReplication === true) {
+            context.imageSmoothingEnabled = false;
+            context.mozImageSmoothingEnabled = false; // firefox doesn't support imageSmoothingEnabled yet
+        }
+        else {
+            context.imageSmoothingEnabled = true;
+            context.mozImageSmoothingEnabled = true;
+        }
+
+        // save the canvas context state and apply the viewport properties
+        context.save();
+        cornerstone.setToPixelCoordinateSystem(enabledElement, context);
+
+        var renderCanvas = getRenderCanvas(enabledElement, image, invalidated);
+
+        context.drawImage(renderCanvas, 0,0, image.width, image.height, 0, 0, image.width, image.height);
+
+        context.restore();
+
+        lastRenderedImageId = image.imageId;
+        lastRenderedViewport.windowCenter = enabledElement.viewport.voi.windowCenter;
+        lastRenderedViewport.windowWidth = enabledElement.viewport.voi.windowWidth;
+        lastRenderedViewport.invert = enabledElement.viewport.invert;
+        lastRenderedViewport.rotation = enabledElement.viewport.rotation;
+        lastRenderedViewport.hflip = enabledElement.viewport.hflip;
+        lastRenderedViewport.vflip = enabledElement.viewport.vflip;
+    }
+
+    // Module exports
+    cornerstone.rendering.colorImage = renderColorImage;
+    cornerstone.renderColorImage = renderColorImage;
+}(cornerstone));
+
+/**
+ * This module is responsible for drawing a grayscale imageß
+ */
+
+(function (cornerstone) {
+
+    "use strict";
+
+    var grayscaleRenderCanvas = document.createElement('canvas');
+    var grayscaleRenderCanvasContext;
+    var grayscaleRenderCanvasData;
+
+    var lastRenderedImageId;
+    var lastRenderedViewport = {};
+
+    function initializeGrayscaleRenderCanvas(image)
+    {
+        // Resize the canvas
+        grayscaleRenderCanvas.width = image.width;
+        grayscaleRenderCanvas.height = image.height;
+
+        // NOTE - we need to fill the render canvas with white pixels since we control the luminance
+        // using the alpha channel to improve rendering performance.
+        grayscaleRenderCanvasContext = grayscaleRenderCanvas.getContext('2d');
+        grayscaleRenderCanvasContext.fillStyle = 'white';
+        grayscaleRenderCanvasContext.fillRect(0,0, grayscaleRenderCanvas.width, grayscaleRenderCanvas.height);
+        grayscaleRenderCanvasData = grayscaleRenderCanvasContext.getImageData(0,0,image.width, image.height);
+    }
+
+    function lutMatches(a, b) {
+      // if undefined, they are equal
+      if(!a && !b) {
+        return true;
+      }
+      // if one is undefined, not equal
+      if(!a || !b) {
+        return false;
+      }
+      // check the unique ids
+      return (a.id !== b.id)
+    }
+
+    function getLut(image, viewport, invalidated)
+    {
+        // if we have a cached lut and it has the right values, return it immediately
+        if(image.lut !== undefined &&
+            image.lut.windowCenter === viewport.voi.windowCenter &&
+            image.lut.windowWidth === viewport.voi.windowWidth &&
+            lutMatches(image.lut.modalityLUT, viewport.modalityLUT) &&
+            lutMatches(image.lut.voiLUT, viewport.voiLUT) &&
+            image.lut.invert === viewport.invert &&
+            invalidated !== true) {
+            return image.lut;
+        }
+
+        // lut is invalid or not present, regenerate it and cache it
+        cornerstone.generateLut(image, viewport.voi.windowWidth, viewport.voi.windowCenter, viewport.invert, viewport.modalityLUT, viewport.voiLUT);
+        image.lut.windowWidth = viewport.voi.windowWidth;
+        image.lut.windowCenter = viewport.voi.windowCenter;
+        image.lut.invert = viewport.invert;
+        image.lut.voiLUT = viewport.voiLUT;
+        image.lut.modalityLUT = viewport.modalityLUT;
+        return image.lut;
+    }
+
+    function doesImageNeedToBeRendered(enabledElement, image)
+    {
+        if(image.imageId !== lastRenderedImageId ||
+            lastRenderedViewport.windowCenter !== enabledElement.viewport.voi.windowCenter ||
+            lastRenderedViewport.windowWidth !== enabledElement.viewport.voi.windowWidth ||
+            lastRenderedViewport.invert !== enabledElement.viewport.invert ||
+            lastRenderedViewport.rotation !== enabledElement.viewport.rotation ||
+            lastRenderedViewport.hflip !== enabledElement.viewport.hflip ||
+            lastRenderedViewport.vflip !== enabledElement.viewport.vflip ||
+            lastRenderedViewport.modalityLUT !== enabledElement.viewport.modalityLUT ||
+            lastRenderedViewport.voiLUT !== enabledElement.viewport.voiLUT
+            )
+        {
+            return true;
+        }
+
+        return false;
+    }
+
+    function getRenderCanvas(enabledElement, image, invalidated)
+    {
+        // apply the lut to the stored pixel data onto the render canvas
+
+        if(doesImageNeedToBeRendered(enabledElement, image) === false && invalidated !== true) {
+            return grayscaleRenderCanvas;
+        }
+
+        // If our render canvas does not match the size of this image reset it
+        // NOTE: This might be inefficient if we are updating multiple images of different
+        // sizes frequently.
+        if(grayscaleRenderCanvas.width !== image.width || grayscaleRenderCanvas.height != image.height) {
+            initializeGrayscaleRenderCanvas(image);
+        }
+
+        // get the lut to use
+        var lut = getLut(image, enabledElement.viewport, invalidated);
+        // gray scale image - apply the lut and put the resulting image onto the render canvas
+        cornerstone.storedPixelDataToCanvasImageData(image, lut, grayscaleRenderCanvasData.data);
+        grayscaleRenderCanvasContext.putImageData(grayscaleRenderCanvasData, 0, 0);
+        return grayscaleRenderCanvas;
+    }
+
+    /**
+     * API function to draw a grayscale image to a given enabledElement
+     * @param enabledElement
+     * @param invalidated - true if pixel data has been invaldiated and cached rendering should not be used
+     */
+    function renderGrayscaleImage(enabledElement, invalidated) {
+
+        if(enabledElement === undefined) {
+            throw "drawImage: enabledElement parameter must not be undefined";
+        }
+        var image = enabledElement.image;
+        if(image === undefined) {
+            throw "drawImage: image must be loaded before it can be drawn";
+        }
+
+        // get the canvas context and reset the transform
+        var context = enabledElement.canvas.getContext('2d');
+        context.setTransform(1, 0, 0, 1, 0, 0);
+
+        // clear the canvas
+        context.fillStyle = 'black';
+        context.fillRect(0,0, enabledElement.canvas.width, enabledElement.canvas.height);
+
+        // turn off image smooth/interpolation if pixelReplication is set in the viewport
+        if(enabledElement.viewport.pixelReplication === true) {
+            context.imageSmoothingEnabled = false;
+            context.mozImageSmoothingEnabled = false; // firefox doesn't support imageSmoothingEnabled yet
+        }
+        else {
+            context.imageSmoothingEnabled = true;
+            context.mozImageSmoothingEnabled = true;
+        }
+
+        // save the canvas context state and apply the viewport properties
+        cornerstone.setToPixelCoordinateSystem(enabledElement, context);
+
+        var renderCanvas = getRenderCanvas(enabledElement, image, invalidated);
+
+        // Draw the render canvas half the image size (because we set origin to the middle of the canvas above)
+        context.drawImage(renderCanvas, 0,0, image.width, image.height, 0, 0, image.width, image.height);
+
+        lastRenderedImageId = image.imageId;
+        lastRenderedViewport.windowCenter = enabledElement.viewport.voi.windowCenter;
+        lastRenderedViewport.windowWidth = enabledElement.viewport.voi.windowWidth;
+        lastRenderedViewport.invert = enabledElement.viewport.invert;
+        lastRenderedViewport.rotation = enabledElement.viewport.rotation;
+        lastRenderedViewport.hflip = enabledElement.viewport.hflip;
+        lastRenderedViewport.vflip = enabledElement.viewport.vflip;
+        lastRenderedViewport.modalityLUT = enabledElement.viewport.modalityLUT;
+        lastRenderedViewport.voiLUT = enabledElement.viewport.voiLUT;
+    }
+
+    // Module exports
+    cornerstone.rendering.grayscaleImage = renderGrayscaleImage;
+    cornerstone.renderGrayscaleImage = renderGrayscaleImage;
+
+}(cornerstone));
+
+/**
+ * This module is responsible for drawing an image to an enabled elements canvas element
+ */
+
+(function (cornerstone) {
+
+    "use strict";
+
+    /**
+     * API function to draw a standard web image (PNG, JPG) to an enabledImage
+     *
+     * @param enabledElement
+     * @param invalidated - true if pixel data has been invaldiated and cached rendering should not be used
+     */
+    function renderWebImage(enabledElement, invalidated) {
+
+        if(enabledElement === undefined) {
+            throw "drawImage: enabledElement parameter must not be undefined";
+        }
+        var image = enabledElement.image;
+        if(image === undefined) {
+            throw "drawImage: image must be loaded before it can be drawn";
+        }
+
+        // get the canvas context and reset the transform
+        var context = enabledElement.canvas.getContext('2d');
+        context.setTransform(1, 0, 0, 1, 0, 0);
+
+        // clear the canvas
+        context.fillStyle = 'black';
+        context.fillRect(0,0, enabledElement.canvas.width, enabledElement.canvas.height);
+
+        // turn off image smooth/interpolation if pixelReplication is set in the viewport
+        if(enabledElement.viewport.pixelReplication === true) {
+            context.imageSmoothingEnabled = false;
+            context.mozImageSmoothingEnabled = false; // firefox doesn't support imageSmoothingEnabled yet
+        }
+        else {
+            context.imageSmoothingEnabled = true;
+            context.mozImageSmoothingEnabled = true;
+        }
+
+        // save the canvas context state and apply the viewport properties
+        cornerstone.setToPixelCoordinateSystem(enabledElement, context);
+
+        // if the viewport ww/wc and invert all match the initial state of the image, we can draw the image
+        // directly.  If any of those are changed, we call renderColorImage() to apply the lut
+        if(enabledElement.viewport.voi.windowWidth === enabledElement.image.windowWidth &&
+            enabledElement.viewport.voi.windowCenter === enabledElement.image.windowCenter &&
+            enabledElement.viewport.invert === false)
+        {
+            context.drawImage(image.getImage(), 0, 0, image.width, image.height, 0, 0, image.width, image.height);
+        } else {
+            cornerstone.renderColorImage(enabledElement, invalidated);
+        }
+
+    }
+
+    // Module exports
+    cornerstone.rendering.webImage = renderWebImage;
+    cornerstone.renderWebImage = renderWebImage;
+
+}(cornerstone));
+/**
+ */
+(function (cornerstone) {
+
+  "use strict";
+
+  /**
+   * Resets the viewport to the default settings
+   *
+   * @param element
+   */
+  function reset(element)
+  {
+    var enabledElement = cornerstone.getEnabledElement(element);
+    var defaultViewport = cornerstone.internal.getDefaultViewport(enabledElement.canvas, enabledElement.image);
+    enabledElement.viewport = defaultViewport;
+    cornerstone.updateImage(element);
+  }
+
+  cornerstone.reset = reset;
+}(cornerstone));
+
+/**
+ * This module is responsible for enabling an element to display images with cornerstone
+ */
+(function (cornerstone) {
+
+    "use strict";
+
+    function setCanvasSize(element, canvas)
+    {
+        // the device pixel ratio is 1.0 for normal displays and > 1.0
+        // for high DPI displays like Retina
+        /*
+
+        This functionality is disabled due to buggy behavior on systems with mixed DPI's.  If the canvas
+        is created on a display with high DPI (e.g. 2.0) and then the browser window is dragged to
+        a different display with a different DPI (e.g. 1.0), the canvas is not recreated so the pageToPixel
+        produces incorrect results.  I couldn't find any way to determine when the DPI changed other than
+        by polling which is not very clean.  If anyone has any ideas here, please let me know, but for now
+        we will disable this functionality.  We may want
+        to add a mechanism to optionally enable this functionality if we can determine it is safe to do
+        so (e.g. iPad or iPhone or perhaps enumerate the displays on the system.  I am choosing
+        to be cautious here since I would rather not have bug reports or safety issues related to this
+        scenario.
+
+        var devicePixelRatio = window.devicePixelRatio;
+        if(devicePixelRatio === undefined) {
+            devicePixelRatio = 1.0;
+        }
+        */
+
+        canvas.width = element.clientWidth;
+        canvas.height = element.clientHeight;
+        canvas.style.width = element.clientWidth + "px";
+        canvas.style.height = element.clientHeight + "px";
+    }
+
+    /**
+     * resizes an enabled element and optionally fits the image to window
+     * @param element
+     * @param fitToWindow true to refit, false to leave viewport parameters as they are
+     */
+    function resize(element, fitToWindow) {
+
+        var enabledElement = cornerstone.getEnabledElement(element);
+
+        setCanvasSize(element, enabledElement.canvas);
+
+        if(enabledElement.image === undefined ) {
+            return;
+        }
+
+        if(fitToWindow === true) {
+            cornerstone.fitToWindow(element);
+        }
+        else {
+            cornerstone.updateImage(element);
+        }
+    }
+
+    // module/private exports
+    cornerstone.resize = resize;
+
+}(cornerstone));
+/**
+ * This module contains a function that will set the canvas context to the pixel coordinates system
+ * making it easy to draw geometry on the image
+ */
+
+(function (cornerstone) {
+
+    "use strict";
+
+    /**
+     * Sets the canvas context transformation matrix to the pixel coordinate system.  This allows
+     * geometry to be driven using the canvas context using coordinates in the pixel coordinate system
+     * @param ee
+     * @param context
+     * @param scale optional scaler to apply
+     */
+    function setToPixelCoordinateSystem(enabledElement, context, scale)
+    {
+        if(enabledElement === undefined) {
+            throw "setToPixelCoordinateSystem: parameter enabledElement must not be undefined";
+        }
+        if(context === undefined) {
+            throw "setToPixelCoordinateSystem: parameter context must not be undefined";
+        }
+
+        var transform = cornerstone.internal.calculateTransform(enabledElement, scale);
+        context.setTransform(transform.m[0],transform.m[1],transform.m[2],transform.m[3],transform.m[4],transform.m[5],transform.m[6]);
+    }
+
+    // Module exports
+    cornerstone.setToPixelCoordinateSystem = setToPixelCoordinateSystem;
+}(cornerstone));
+/**
+ * This module contains functions to deal with getting and setting the viewport for an enabled element
+ */
+(function (cornerstone) {
+
+    "use strict";
+
+    /**
+     * Sets the viewport for an element and corrects invalid values
+     *
+     * @param element - DOM element of the enabled element
+     * @param viewport - Object containing the viewport properties
+     * @returns {*}
+     */
+    function setViewport(element, viewport) {
+
+        var enabledElement = cornerstone.getEnabledElement(element);
+
+        enabledElement.viewport.scale = viewport.scale;
+        enabledElement.viewport.translation.x = viewport.translation.x;
+        enabledElement.viewport.translation.y = viewport.translation.y;
+        enabledElement.viewport.voi.windowWidth = viewport.voi.windowWidth;
+        enabledElement.viewport.voi.windowCenter = viewport.voi.windowCenter;
+        enabledElement.viewport.invert = viewport.invert;
+        enabledElement.viewport.pixelReplication = viewport.pixelReplication;
+        enabledElement.viewport.rotation = viewport.rotation;
+        enabledElement.viewport.hflip = viewport.hflip;
+        enabledElement.viewport.vflip = viewport.vflip;
+        enabledElement.viewport.modalityLUT = viewport.modalityLUT;
+        enabledElement.viewport.voiLUT = viewport.voiLUT;
+
+        // prevent window width from being too small (note that values close to zero are valid and can occur with
+        // PET images in particular)
+        if(enabledElement.viewport.voi.windowWidth < 0.000001) {
+            enabledElement.viewport.voi.windowWidth = 0.000001;
+        }
+        // prevent scale from getting too small
+        if(enabledElement.viewport.scale < 0.0001) {
+            enabledElement.viewport.scale = 0.25;
+        }
+
+        if(enabledElement.viewport.rotation===360 || enabledElement.viewport.rotation===-360) {
+            enabledElement.viewport.rotation = 0;
+        }
+
+        // Force the image to be updated since the viewport has been modified
+        cornerstone.updateImage(element);
+    }
+
+
+    // module/private exports
+    cornerstone.setViewport = setViewport;
+
+}(cornerstone));
+
+/**
+ * This module contains a function to immediately redraw an image
+ */
+(function (cornerstone) {
+
+    "use strict";
+
+    /**
+     * Forces the image to be updated/redrawn for the specified enabled element
+     * @param element
+     */
+    function updateImage(element, invalidated) {
+        var enabledElement = cornerstone.getEnabledElement(element);
+
+        if(enabledElement.image === undefined) {
+            throw "updateImage: image has not been loaded yet";
+        }
+
+        cornerstone.drawImage(enabledElement, invalidated);
+    }
+
+    // module exports
+    cornerstone.updateImage = updateImage;
+
+}(cornerstone));
\ No newline at end of file

Modified: trunk/packages/orthanc-webviewer/trunk/debian/changelog
===================================================================
--- trunk/packages/orthanc-webviewer/trunk/debian/changelog	2015-12-06 21:13:17 UTC (rev 20663)
+++ trunk/packages/orthanc-webviewer/trunk/debian/changelog	2015-12-07 15:27:48 UTC (rev 20664)
@@ -1,3 +1,9 @@
+orthanc-webviewer (2.0-2) UNRELEASED; urgency=medium
+
+  * Upgrade Cornerstone version: 0.7.1 to 0.8.4
+
+ -- Sebastien Jodogne <s.jodogne at gmail.com>  Mon, 07 Dec 2015 16:23:47 +0100
+
 orthanc-webviewer (2.0-1) unstable; urgency=medium
 
   * New upstream version.

Modified: trunk/packages/orthanc-webviewer/trunk/debian/rules
===================================================================
--- trunk/packages/orthanc-webviewer/trunk/debian/rules	2015-12-06 21:13:17 UTC (rev 20663)
+++ trunk/packages/orthanc-webviewer/trunk/debian/rules	2015-12-07 15:27:48 UTC (rev 20664)
@@ -28,9 +28,9 @@
 
         # Place the third-party JavaScript libraries at the location
         # expected by CMake
-	yui-compressor debian/JS/cornerstone-0.7.1/cornerstone.js > \
+	yui-compressor debian/JS/cornerstone-0.8.4/cornerstone.js > \
 		${JAVASCRIPT_LIBS}/cornerstone.min.js
-	yui-compressor debian/JS/cornerstone-0.7.1/cornerstone.css > \
+	yui-compressor debian/JS/cornerstone-0.8.4/cornerstone.css > \
 		${JAVASCRIPT_LIBS}/cornerstone.min.css
 
 	yui-compressor debian/JS/jsPanel-2.3.3/jquery.jspanel.js > \




More information about the debian-med-commit mailing list