ivmartel / dwv

DICOM Web Viewer: open source zero footprint medical image library.
https://ivmartel.github.io/dwv/
GNU General Public License v3.0
1.64k stars 588 forks source link

Switching between multiple images #1712

Open stylekilla opened 1 month ago

stylekilla commented 1 month ago

Hi ivmartel,

Nice work on creating and maintaining DWV. I've been trying to get dwv (through npm install, v0.33) to work as a simple dicom image viewer in react (v18), but I'm having some trouble and was hoping to get some help.

I have read all of your documentation, the examples, and explored the provided dwv-react git repo. Admittedly, I have found the documentation somewhat difficult to follow (both javascript and react are fairly new to me).

I have three independent dicom images that I want to view one at a time, changing the image . I have generated three buttons that each pass their ID to the DWV component as a prop (see below). The images render, but instead of overwriting what is in the layerGroup it creates a new layer within the group and I end up with three div's each with an id of layerGroup0-layer0 (see below).

Is there something basic I have missed about how DWV works? I also can't workout why the size of each image double the size of the previous.

Any help is appreciated, Thank you.

import React, { useEffect } from 'react';

import * as dwv from 'dwv';

export default function DvwComponent(props) {
  var app = new dwv.App();
  var options = new dwv.AppOptions();
  var viewConfig = new dwv.ViewConfig("layerGroup0");
  viewConfig.colourMap = "plain";
  viewConfig.opacity = 1;

  options.viewOnFirstLoadItem = true;
  options.dataViewConfigs = {'*': [viewConfig]};

  app.init(options);

  useEffect(() => {
    app.loadImageObject([props.imageObjects[props.currentImageIndex]]);
  }, [props.currentImageIndex])

  return (
    <div id="dwv">
      <div id="layerGroup0" className="layerGroup"></div>
    </div>
  )
}

Updating props.currentImageIndex three times gives:

<div id="dwv">
  <div id="layerGroup0" class="layerGroup">
    <div id="layerGroup0-layer-0" class="layer viewLayer" style="pointer-events: none;">
      <canvas width="1629" height="154"></canvas>
    </div>
    <div id="layerGroup0-layer-0" class="layer viewLayer" style="pointer-events: none;">
      <canvas width="1629" height="312"></canvas>
    </div>
    <div id="layerGroup0-layer-0" class="layer viewLayer" style="pointer-events: none;">
      <canvas width="1629" height="628"></canvas>
    </div>
  </div>
</div>
stylekilla commented 1 month ago

I'm not sure if it's helpful but I thought I would provide some additional information. Say I have 3 images in the form imageObjects = [{ name: str, filename: str, data: ArrayBuffer }, ..., ...], when I use app.loadImageObject([props.imageObjects]) I would expect the app to create three new dataIdss: ['0', '1', '2']. Doing some digging, it seems as though it should at least return one dataId (as per code from src/app/application.js:780 noted below). Instead, if I run app.getDataIds(); after loading my image data, I get an empty list [].

loadImageObject = (data) => {
  // Get new data id
  const dataId = this.#dataController.getNextDataId();
  this.#loadController.loadImageObject(data, dataId);
};

However, if I only load ONE image (instead of three) then it returns ['0'], and then each time I load a new image I get the aforementioned behaviour of having multiple divs with the same properties but a different image, each div doubling in height.

Another question: when submitting three images in one action to be loaded and with only one dataId value being created, how do I access each of the three images I uploaded?

ivmartel commented 1 month ago

Hi, thanks for trying dwv! The layerGroup is meant to display similar images on top of each others with some opacity at each layer. I created a fiddle as a simple example: https://jsfiddle.net/ivmartel/pvghxj1y/. The same data is loaded twice, you can toggle them by changing their opacity. Careful if you load un-related data, dwv shows data at a given position, if both images are not at that same position, one will be blank. Regarding dataIds, the app.load methods load multiple buffers that make one data, typically these buffers are the different slices of that data. If you want to load different data, you have to call a load method for each. The 'div doubling' must be related to your html/css, in order to display data on top of each other, the .layer class must have position: absolute;.

ivmartel commented 13 hours ago

Hi @stylekilla, did you make some progress with your issue?