UNPKG

cornerstone-tools-cacalc

Version:

Medical imaging tools for the Cornerstone library with added functionality for computing Agatston calcium scores

320 lines (249 loc) 10.3 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>stackTools/playClip.js - Documentation</title> <script src="scripts/prettify/prettify.js"></script> <script src="scripts/prettify/lang-css.js"></script> <!--[if lt IE 9]> <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> <link type="text/css" rel="stylesheet" href="styles/prettify.css"> <link type="text/css" rel="stylesheet" href="styles/jsdoc.css"> </head> <body> <input type="checkbox" id="nav-trigger" class="nav-trigger" /> <label for="nav-trigger" class="navicon-button x"> <div class="navicon"></div> </label> <label for="nav-trigger" class="overlay"></label> <nav> <h2><a href="index.html">Home</a></h2><h3>Global</h3><ul><li><a href="global.html#applyWWWCRegion">applyWWWCRegion</a></li><li><a href="global.html#calculateMinMaxMean">calculateMinMaxMean</a></li><li><a href="global.html#createMagnificationCanvas">createMagnificationCanvas</a></li><li><a href="global.html#dragCallback">dragCallback</a></li><li><a href="global.html#drawMagnificationTool">drawMagnificationTool</a></li><li><a href="global.html#getPlayClipTimeouts">getPlayClipTimeouts</a></li><li><a href="global.html#mouseDownCallback">mouseDownCallback</a></li><li><a href="global.html#mouseUpCallback">mouseUpCallback</a></li><li><a href="global.html#onImageRendered">onImageRendered</a></li><li><a href="global.html#performThresholding">performThresholding</a></li><li><a href="global.html#playClip">playClip</a></li><li><a href="global.html#recordStartPoint">recordStartPoint</a></li><li><a href="global.html#removeMagnificationCanvas">removeMagnificationCanvas</a></li><li><a href="global.html#stopClip">stopClip</a></li><li><a href="global.html#stopClipWithData">stopClipWithData</a></li><li><a href="global.html#triggerStopEvent">triggerStopEvent</a></li></ul> </nav> <div id="main"> <h1 class="page-title">stackTools/playClip.js</h1> <section> <article> <pre class="prettyprint source linenums"><code>/* eslint no-bitwise:0 */ import $ from '../jquery.js'; import * as cornerstone from '../cornerstone-core.js'; import loadHandlerManager from '../stateManagement/loadHandlerManager.js'; import { addToolState, getToolState } from '../stateManagement/toolState.js'; const toolType = 'playClip'; /** * [private] Turns a Frame Time Vector (0018,1065) array into a normalized array of timeouts. Each element * ... of the resulting array represents the amount of time each frame will remain on the screen. * @param {Array} vector A Frame Time Vector (0018,1065) as specified in section C.7.6.5.1.2 of DICOM standard. * @param {Number} speed A speed factor which will be applied to each element of the resulting array. * @return {Array} An array with timeouts for each animation frame. */ function getPlayClipTimeouts (vector, speed) { let i; let sample; let delay; let sum = 0; const limit = vector.length; const timeouts = []; // Initialize time varying to false timeouts.isTimeVarying = false; if (typeof speed !== 'number' || speed &lt;= 0) { speed = 1; } // First element of a frame time vector must be discarded for (i = 1; i &lt; limit; i++) { delay = (Number(vector[i]) / speed) | 0; // Integral part only timeouts.push(delay); if (i === 1) { // Use first item as a sample for comparison sample = delay; } else if (delay !== sample) { timeouts.isTimeVarying = true; } sum += delay; } if (timeouts.length > 0) { if (timeouts.isTimeVarying) { // If it's a time varying vector, make the last item an average... delay = (sum / timeouts.length) | 0; } else { delay = timeouts[0]; } timeouts.push(delay); } return timeouts; } /** * [private] Performs the heavy lifting of stopping an ongoing animation. * @param {Object} playClipData The data from playClip that needs to be stopped. * @return void */ function stopClipWithData (playClipData) { const id = playClipData.intervalId; if (typeof id !== 'undefined') { playClipData.intervalId = undefined; if (playClipData.usingFrameTimeVector) { clearTimeout(id); } else { clearInterval(id); } } } /** * [private] Trigger playClip tool stop event. * @param element * @return void */ function triggerStopEvent (element) { const eventDetail = { element }; const event = $.Event('CornerstoneToolsClipStopped', eventDetail); $(element).trigger(event, eventDetail); } /** * Starts playing a clip or adjusts the frame rate of an already playing clip. framesPerSecond is * optional and defaults to 30 if not specified. A negative framesPerSecond will play the clip in reverse. * The element must be a stack of images * @param element * @param framesPerSecond */ function playClip (element, framesPerSecond) { let playClipData; let playClipTimeouts; if (element === undefined) { throw new Error('playClip: element must not be undefined'); } const stackToolData = getToolState(element, 'stack'); if (!stackToolData || !stackToolData.data || !stackToolData.data.length) { return; } const stackData = stackToolData.data[0]; const playClipToolData = getToolState(element, toolType); if (!playClipToolData || !playClipToolData.data || !playClipToolData.data.length) { playClipData = { intervalId: undefined, framesPerSecond: 30, lastFrameTimeStamp: undefined, frameRate: 0, frameTimeVector: undefined, ignoreFrameTimeVector: false, usingFrameTimeVector: false, speed: 1, reverse: false, loop: true }; addToolState(element, toolType, playClipData); } else { playClipData = playClipToolData.data[0]; // Make sure the specified clip is not running before any property update stopClipWithData(playClipData); } // If a framesPerSecond is specified and is valid, update the playClipData now if (framesPerSecond &lt; 0 || framesPerSecond > 0) { playClipData.framesPerSecond = Number(framesPerSecond); playClipData.reverse = playClipData.framesPerSecond &lt; 0; // If framesPerSecond is given, frameTimeVector will be ignored... playClipData.ignoreFrameTimeVector = true; } // Determine if frame time vector should be used instead of a fixed frame rate... if ( playClipData.ignoreFrameTimeVector !== true &amp;&amp; playClipData.frameTimeVector &amp;&amp; playClipData.frameTimeVector.length === stackData.imageIds.length ) { playClipTimeouts = getPlayClipTimeouts(playClipData.frameTimeVector, playClipData.speed); } // This function encapsulates the frame rendering logic... const playClipAction = () => { // Hoisting of context variables let loader, viewport, startLoadingHandler, endLoadingHandler, errorLoadingHandler, newImageIdIndex = stackData.currentImageIdIndex; const imageCount = stackData.imageIds.length; if (playClipData.reverse) { newImageIdIndex--; } else { newImageIdIndex++; } if (!playClipData.loop &amp;&amp; (newImageIdIndex &lt; 0 || newImageIdIndex >= imageCount)) { stopClipWithData(playClipData); triggerStopEvent(element); return; } // Loop around if we go outside the stack if (newImageIdIndex >= imageCount) { newImageIdIndex = 0; } if (newImageIdIndex &lt; 0) { newImageIdIndex = imageCount - 1; } if (newImageIdIndex !== stackData.currentImageIdIndex) { startLoadingHandler = loadHandlerManager.getStartLoadHandler(); endLoadingHandler = loadHandlerManager.getEndLoadHandler(); errorLoadingHandler = loadHandlerManager.getErrorLoadingHandler(); if (startLoadingHandler) { startLoadingHandler(element); } viewport = cornerstone.getViewport(element); if (stackData.preventCache === true) { loader = cornerstone.loadImage(stackData.imageIds[newImageIdIndex]); } else { loader = cornerstone.loadAndCacheImage(stackData.imageIds[newImageIdIndex]); } loader.then(function (image) { stackData.currentImageIdIndex = newImageIdIndex; cornerstone.displayImage(element, image, viewport); if (endLoadingHandler) { endLoadingHandler(element, image); } }, function (error) { const imageId = stackData.imageIds[newImageIdIndex]; if (errorLoadingHandler) { errorLoadingHandler(element, imageId, error); } }); } }; // If playClipTimeouts array is available, not empty and its elements are NOT uniform ... // ... (at least one timeout is different from the others), use alternate setTimeout implementation if (playClipTimeouts &amp;&amp; playClipTimeouts.length > 0 &amp;&amp; playClipTimeouts.isTimeVarying) { playClipData.usingFrameTimeVector = true; playClipData.intervalId = setTimeout(function playClipTimeoutHandler () { playClipData.intervalId = setTimeout(playClipTimeoutHandler, playClipTimeouts[stackData.currentImageIdIndex]); playClipAction(); }, 0); } else { // ... otherwise user setInterval implementation which is much more efficient. playClipData.usingFrameTimeVector = false; playClipData.intervalId = setInterval(playClipAction, 1000 / Math.abs(playClipData.framesPerSecond)); } } /** * Stops an already playing clip. * * @param element */ function stopClip (element) { const playClipToolData = getToolState(element, toolType); if (!playClipToolData || !playClipToolData.data || !playClipToolData.data.length) { return; } stopClipWithData(playClipToolData.data[0]); } export { playClip, stopClip }; </code></pre> </article> </section> </div> <br class="clear"> <footer> Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.4</a> using the <a href="https://github.com/clenemt/docdash">docdash</a> theme. </footer> <script>prettyPrint();</script> <script src="scripts/linenumber.js"></script> </body> </html>