cornerstonejs / cornerstone3D

Cornerstone is a set of JavaScript libraries that can be used to build web-based medical imaging applications. It provides a framework to build radiology applications such as the OHIF Viewer.
https://cornerstonejs.org
MIT License
473 stars 249 forks source link

[Bug] CINE tool playClip for wadouri dicom loader doesn't work properly. #803

Open issaharw opened 9 months ago

issaharw commented 9 months ago

Describe the Bug

I'm using the CINE tool to play a clip like that: utilities.cine.playClip(element, { "framesPerSecond": 30 }); But the clip doesn't play. It is very jumpy, and jumps strait to the last frame and back to the first one. I've looked at the code and found out that inside playClip.ts there is a debounce variable that is always set to true and therefore the player waits and doesn't play. When I change the variable to false, everything works perfectly.

Notes:

  1. If you use 20 framesPerSecond, it plays very slowly and only after like 5 times the clip was played, it is played in the correct speed. But 25 frames per second and above - it doesn't work.
  2. I'm using WADO-URI loader, which has a built-in cache, so the dicom file is actually loaded only once from the server.
  3. If I'm using window.setInterval and inside it viewport.setImageIndexId, it works like a charm.

Steps to Reproduce

Use the below code inside index.tx of the tutorial example (just change the url of the dicom):

import { RenderingEngine, Enums } from '@cornerstonejs/core';
import { utilities } from '@cornerstonejs/tools';
import { setTitleAndDescription } from '../../../../utils/demo/helpers';
import cornerstoneDICOMImageLoader from '@cornerstonejs/dicom-image-loader';
import dicomParser from 'dicom-parser';
import * as cornerstone from '@cornerstonejs/core';
import * as cornerstoneTools from '@cornerstonejs/tools';

const { preferSizeOverAccuracy, useNorm16Texture } = cornerstone.getConfiguration().rendering;

function initCornerstoneDICOMImageLoader() {
  cornerstoneDICOMImageLoader.external.cornerstone = cornerstone;
  cornerstoneDICOMImageLoader.external.dicomParser = dicomParser;
  cornerstoneDICOMImageLoader.configure({
    useWebWorkers: true,
    decodeConfig: {
      convertFloatPixelDataToInt: false,
      use16BitDataType: preferSizeOverAccuracy || useNorm16Texture,
    },
  });

  let maxWebWorkers = 1;

  if (navigator.hardwareConcurrency) {
    maxWebWorkers = Math.min(navigator.hardwareConcurrency, 7);
  }

  var config = {
    maxWebWorkers,
    startWebWorkersOnDemand: false,
    taskConfiguration: {
      decodeTask: {
        initializeCodecsOnStartup: false,
        strict: false,
      },
    },
  };

  cornerstoneDICOMImageLoader.webWorkerManager.initialize(config);
}

// This is for debugging purposes
console.warn(
  'Click on index.ts to open source code for this example --------->'
);

// ============================= //
// ======== Set up page ======== //
setTitleAndDescription(
  'Tutorial Playground',
  'The playground for you to copy paste the codes in the tutorials and run it'
);

const { ViewportType } = Enums;
/**
 * Runs the demo
 */
async function run() {
  // Init Cornerstone and related libraries
  initCornerstoneDICOMImageLoader();
  await cornerstone.init();
  await cornerstoneTools.init();

  const content = document.getElementById('content');
  const element = document.createElement('div');
  element.style.width = '500px';
  element.style.height = '500px';

  content.appendChild(element);
  // const arrayBuffer = await fetchDICOM();
  // const dataSet = parseDICOM(arrayBuffer);
  const url = "http://localhost:8080/wado-get/studies/1.2.840.113564.99.1.147715611861.1313741.201814133652343.71.2.9/instances/1.2.840.113619.2.391.1603.1515073441.3.1.512"
  // const dataset = await cornerstoneDICOMImageLoader.wadouri.dataSetCacheManager.load(url)
  // console.log(dataset)
  const imageIds = []

  var numFrames = 76 //dataset.intString('x00280008');
  const frameRate = 20 // 1000/dataset.floatString('x00181063');
  console.log(numFrames)
  for(var i=1; i <= numFrames; i++) {
      var imageId = "wadouri:" + url + "?frame="+i;
      imageIds.push(imageId);
  }

  const renderingEngineId = 'myRenderingEngine';
  const viewportId = 'CT_AXIAL_STACK';
  const renderingEngine = new RenderingEngine(renderingEngineId);

  const viewportInput = {
    viewportId,
    element,
    type: ViewportType.STACK,
  };

  renderingEngine.enableElement(viewportInput);

  const viewport = renderingEngine.getViewport(viewportInput.viewportId);

  viewport.setStack(imageIds);

  const { IMAGE_RENDERED, CAMERA_MODIFIED, STACK_NEW_IMAGE } = Enums.Events;

  element.addEventListener(IMAGE_RENDERED, (event) => {
    const currentImageIdIndex = viewport.getCurrentImageIdIndex();
    console.log("Current image rendered: " + currentImageIdIndex)
  });

  viewport.render();
  utilities.cine.playClip(element, { "framesPerSecond": frameRate });
}

run();

The current behavior

The clip doesn't play at all, or plays very strangely.

The expected behavior

The clip will play smoothly

OS

macOS

Node version

16.17.0

Browser

Arc

danielraggs commented 3 weeks ago

I was running into the same issues, but this solution greatly improved things for me.