Skip to content

Instantly share code, notes, and snippets.

@swederik
Created September 1, 2015 10:24
Show Gist options
  • Save swederik/2fe7e2f61fb495252d0c to your computer and use it in GitHub Desktop.
Save swederik/2fe7e2f61fb495252d0c to your computer and use it in GitHub Desktop.
/*
Display image loading progress bar across bottom of image.
Display % loaded while image is loading.
*/
(function($, cornerstone, cornerstoneTools) {
"use strict";
var scrollBarHeight = 6;
var progressData = {};
function onImageRendered(e, eventData) {
var element = eventData.element;
var width = eventData.enabledElement.canvas.width;
var height = eventData.enabledElement.canvas.height;
if (!width || !height) {
// image not actually rendered yet, not sure what's going on here
return false;
}
var context = eventData.enabledElement.canvas.getContext("2d");
context.setTransform(1, 0, 0, 1, 0, 0);
context.save();
// draw indicator background
context.fillStyle = 'rgb(19, 63, 141)';
context.fillRect(0, height - scrollBarHeight, width, scrollBarHeight);
// get current image index
var stackData = cornerstoneTools.getToolState(element, 'stack');
if (!stackData || !stackData.data || !stackData.data.length) {
return;
}
var imageIds = stackData.data[0].imageIds;
// draw current image cursor
setLoadedMarker(context, width, height, imageIds);
var data = progressData[element];
if (data && data.percentComplete) {
drawImageLoadIndicator(context, data.percentComplete + '%', width, height);
}
context.restore();
}
function showProgress(event, data) {
var element = event.data.element;
if (!element){
console.error('No element is available for this event.');
return false;
}
var instances = event.data.instances,
enabledElement;
try {
enabledElement = cornerstone.getEnabledElement(element);
} catch (err) {
// this may occur if an element in the midst of prefetching
// is disabled/destroyed.
console.warn('Progress event caught for non-enabled element');
return false;
}
var file = data.fileURL.substring(data.fileURL.indexOf('://'));
var stackData = cornerstoneTools.getToolState(element, 'stack');
var currentImage;
if (stackData && stackData.data && stackData.data[0]){
currentImage = stackData.imageIds[stackData.currentImageIdIndex];
} else {
currentImage = cornerstone.getEnabledElement(element).loadingImageId;
}
if (!currentImage){
return false;
}
var currentImageURL = currentImage.substring(currentImage.indexOf('://'));
if (file !== currentImageURL){
return false;
}
/*
Check if we need to compute the percent complete because it isn't given
in the progress event
*/
if (!data.total) {
if (!instances || !data.loaded){
console.error('Cannot compute progress with the information provided.', instances, data.loaded);
return false;
}
var files = instances.map(function(instance){
return instance.url.substring(instance.url.indexOf('://'));
});
var currentImageIndex = files.indexOf(currentImageURL);
data.total = instances[currentImageIndex].originalSize;
data.percentComplete = Math.round((data.loaded / data.total) * 100);
}
progressData[element] = data;
}
function drawImageLoadIndicator(context, string, width, height) {
var x = width / 2;
var y = height / 2;
context.clearRect( 0, 0, width, height - scrollBarHeight);
context.fillStyle = "white";
context.font = "40px Arial";
context.textAlign = "center";
context.textBaseline = "middle";
context.fillText(string, x, y);
}
function setLoadedMarker(context, width, height, imageIds) {
var numImages = imageIds.length,
unitWidth = width / numImages;
imageIds.forEach(function(imageId, index) {
var imagePromise = cornerstone.imageCache.getImagePromise(imageId);
if (!imagePromise || imagePromise.state() !== "resolved") {
return;
}
var offset = unitWidth * index;
context.fillStyle = 'rgb(44, 154, 255)';
context.fillRect(offset, height - scrollBarHeight, unitWidth, scrollBarHeight);
});
}
function disable(element, instances) {
$(element).off("CornerstoneImageRendered", onImageRendered);
$(document).off("CornerstoneImageLoadProgress", {element: element, instances: instances}, showProgress);
}
/**
* Activate image download indicator for the element
* @param {Object} element DOM element
* @param {Array} instances Optional array of objects with metadata
* for each instance in the stack, useful when loading
* compressed images which do not report total file size
* in XHR progress event. Each instance object needs
* parameters 'url' (String) and 'originalSize' (Integer, in bytes)
*/
function enable(element, instances) {
cornerstoneTools.loadingProgressIndicator.disable(element, instances);
var eventData = {
element: element,
instances: instances
};
$(document).on("CornerstoneImageLoadProgress", eventData, showProgress);
$(element).on("CornerstoneImageRendered", onImageRendered);
}
cornerstoneTools.loadingProgressIndicator = {
enable: enable,
disable: disable
};
})($, cornerstone, cornerstoneTools);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment