Loading Dicom with CornerstoneWadoImageLoader then viewing them in a cornerstone3d viewport

Describe Your Question

Hi. I’m trying to load Dicom files with cornerstone wado image loader then use the loaded files in a cornerstone3d Viewport.

I uploaded the project to github on the following link: GitHub - hugopereiragit/DicomViewer---Development

Following some examples i saw online i am able to upload dicom files directly from the device and view them this can be seen on ./components/loadingImage.ts and looks like this:

I would then like to send these uploaded files to the next page (./components/viewpage) and layer them on top of eachother.Ideialy it should look something like the following: Imgur: The magic of the Internet
But instead of using 3 Dicom files i get from the web I would use the files previously imported in the previous page.

I’m unaware if i’m getting the metadata from the file with cornerstonewadoimageloader or if I should use another method. Any help would be apreciated.

Thank you

What steps can we follow to reproduce the bug?

  1. Clone/download the github link
  2. yarn install
  3. yarn run dev

the 2 important components code blocks are below if you rather see them here instead of github:

> 
> import { useEffect, useRef, useState } from "react"
> import { BrowserRouter as Router, Route, Link } from "react-router-dom";
> import cornerstone from "cornerstone-core"
> import cornerstoneTools from "cornerstone-tools"
> import cornerstoneWADOImageLoader from "cornerstone-wado-image-loader"
> import './old.css'
> import initCornerstone from "../initCornerstone.js"
> import Button from "./CustomButtonComponent";
> 
> initCornerstone()
> 
> function LoadingImages() {
>   const [uploadedFiles, setUploadedFiles] = useState([])
>   const [imageIds, setImageIds] = useState([])
> 
>   let element
> 
> 
>   useEffect(() => {
>     element = document.getElementById("dicomImage");
>     cornerstone.enable(element);
>   });
> 
>   const handleFileChange = (e: any) => {
>     const files = Array.from(e.target.files)
>     setUploadedFiles(files)
>     const imageIds = files.map((file) => {
>       return cornerstoneWADOImageLoader.wadouri.fileManager.add(file)
>     })
>     setImageIds(imageIds)
>     const StackScrollMouseWheelTool = cornerstoneTools.StackScrollMouseWheelTool
> 
>     const stack = {
>       currentImageIdIndex: 0,
>       imageIds,
>     }; console.log(stack);
>     cornerstone.loadImage(imageIds[0]).then((image) => {
>       cornerstone.displayImage(element, image)
>       cornerstoneTools.addStackStateManager(element, ["stack"])
>       cornerstoneTools.addToolState(element, "stack", stack)
>     })
>     setTimeout(() => {
>       imageIds.forEach((imageId) => {
>         const thumbnailElement = document.getElementById(imageId)
>         cornerstone.enable(thumbnailElement)
>         cornerstone.loadImage(imageId).then((image) => {
>           cornerstone.displayImage(thumbnailElement, image)
>           cornerstoneTools.addStackStateManager(element, ["stack"])
>           cornerstoneTools.addToolState(element, "stack", stack)
>         })
>       })
>     }, 1000)
>     cornerstoneTools.addTool(StackScrollMouseWheelTool)
>     cornerstoneTools.setToolActive("StackScrollMouseWheel", {})
>   }
> 
>   const setZoomActive = (e) => {
>     const ZoomMouseWheelTool = cornerstoneTools.ZoomMouseWheelTool;
> 
>     cornerstoneTools.addTool(ZoomMouseWheelTool);
>     cornerstoneTools.setToolActive("ZoomMouseWheel", { mouseButtonMask: 1 });
>     const PanTool = cornerstoneTools.PanTool;
> 
>     cornerstoneTools.addTool(PanTool);
>     cornerstoneTools.setToolActive("Pan", { mouseButtonMask: 1 });
>   };
> 
> 
> 
>   return (
>     
>     <div className="cornerstone">
>       <div className="navBar">
>       <Link to="/" className={location.pathname === "/" ? "activeNavButton navButton" : "navButton"}>
>           Home
>         </Link>
>         <Link to="/LoadingImages" className={location.pathname === "/LoadingImages" ? "activeNavButton navButton" : "navButton"}>
>           Load Dicom Images
>         </Link>
>         <Link to="/viewpage" className={location.pathname === "/viewpage" ? "activeNavButton navButton" : "navButton"}>
>           Viewmodes
>         </Link>
>         <Link to="/Help" className={location.pathname === "/Help" ? "activeNavButton navButton" : "navButton"}>
>           Help
>         </Link>
>         <Link to="/Contacts" className={location.pathname === "/Contacts" ? "activeNavButton navButton" : "navButton"}>
>           Contact Info
>         </Link>
>       </div>
>       <div className="loader">
>         <input type="file" onChange={handleFileChange} multiple />
>         <button onClick={setZoomActive}>Zoom/Pan</button>
>       </div>
>       <div className="dicom-wrapper">
>         <div className="thumbnail-selector">
>           <div className="thumbnail-list" id="thumbnail-list">
>             {imageIds.map((imageId) => {
>               return (
>                 <a
>                   key={imageId}
>                   onContextMenu={() => false}
>                   unselectable="on"
>                   onMouseDown={() => false}
>                   onSelect={() => false}
>                 >
>                   <div
>                     id={imageId}
>                     className="thumbnail-item"
>                     onContextMenu={() => false}
>                     unselectable="on"
>                     onMouseDown={() => false}
>                     onSelect={() => false}
>                   />
>                 </a>
>               )
>             })}
>           </div>
>         </div>
>       </div>
>       <div
>         onContextMenu={() => false}
>         className="dicom-viewer"
>         unselectable="on"
>       >
>       <div id="dicomImage"></div>
>       </div>
>       <Link to={{pathname: "/Viewpage", state: {imageIds: imageIds}}}>
>       <Button 
>         border="none"
>         color="blue"
>         height="200px"
>         onClick={() => console.log(imageIds)}
>         radius="50%"
>         width="200px"
>         children="Continue"
>       />
>       </Link>
>     </div>
>   )
> }
> 
> export default LoadingImages


> import { useEffect, useRef, useState } from "react"
> // import cornerstone from "cornerstone-core"
> import { useLocation, Link } from "react-router-dom";
> import CornerstoneViewport from "react-cornerstone-viewport"
> import cornerstoneTools from "cornerstone-tools"
> import cornerstone from "cornerstone-core"
> 
> // Descomentar para utilizar ficheiros dicom a funcionar
> /*const imageIds = [
>   "dicomweb://s3.amazonaws.com/lury/PTCTStudy/1.3.6.1.4.1.25403.52237031786.3872.20100510032220.9.dcm",
>   "dicomweb://s3.amazonaws.com/lury/PTCTStudy/1.3.6.1.4.1.25403.52237031786.3872.20100510032220.10.dcm",
>   "dicomweb://s3.amazonaws.com/lury/PTCTStudy/1.3.6.1.4.1.25403.52237031786.3872.20100510032220.11.dcm",
> ]
> */
> const imageIds = [
>   "dicomweb://identisoft.pt/test-id1/IMG00000",
>   "dicomweb://identisoft.pt/test-id1/IMG00002",
> ];
> 
> function Viewingpage() {
>   const [activeViewportIndex, setActiveViewportIndex] = useState(0)
>   const [imageIdIndex, setImageIdIndex] = useState(0)
>   const [activeTool, setActiveTool] = useState("Zoom")
>   const viewports = [0, 1]
>   const vpRef = useRef()
> //  const [imageIds, setImageIds] = useState([])
> //  comentar proximas 2 linhas para utilizar as imagens default
>  // const location = useLocation();
>  // const imageIds = location.state?.imageIds;
> 
> //cornerstone.loadImage(imageId).then(
> 
> 
>   
> 
>   const tools = [
>     {
>       name: "Wwwc",
>       mode: "active",
>       modeOptions: { mouseButtonMask: 1 },
>     },
>     {
>       name: "Zoom",
>       mode: "active",
>       modeOptions: { mouseButtonMask: 2 },
>     },
>     {
>       name: "Pan",
>       mode: "active",
>       modeOptions: { mouseButtonMask: 4 },
>     },
>     // Scroll
>     { name: "StackScrollMouseWheel", mode: "active" },
>     // Touch
>     { name: "PanMultiTouch", mode: "active" },
>     { name: "ZoomTouchPinch", mode: "active" },
>     { name: "StackScrollMultiTouch", mode: "active" },
>   ]
> 
> 
>   useEffect(() => {
>     if (vpRef) {
>       const scrollSyn = new cornerstoneTools.Synchronizer(
>         "cornerstonetoolsstackscroll",
>         cornerstoneTools.stackScrollSynchronizer
>       )
>       // console.log("scrollSyn :>> ", scrollSyn)
> 
>       const wwwcSyn = new cornerstoneTools.Synchronizer(
>         "cornerstoneimagerendered",
>         cornerstoneTools.wwwcSynchronizer
>       )
> 
>       const zoomSyn = new cornerstoneTools.Synchronizer(
>         "cornerstoneimagerendered",
>         cornerstoneTools.panZoomSynchronizer
>       )
> 
>       const res = document.getElementsByClassName("viewport-element")
>       const left = res[0]
>       const right = res[1]
> 
>       cornerstone.enable(left)
>       cornerstone.enable(right)
> 
>       scrollSyn.add(left)
>       scrollSyn.add(right)
> 
>       wwwcSyn.add(left)
>       wwwcSyn.add(right)
> 
>       zoomSyn.add(left)
>       zoomSyn.add(right)
>     }
>   }, [vpRef])
> 
>   return (
>     <div className="viewpage">
>             <div className="navBar">
>       <Link to="/" className={location.pathname === "/" ? "activeNavButton navButton" : "navButton"}>
>           Home
>         </Link>
>         <Link to="/LoadingImages" className={location.pathname === "/LoadingImages" ? "activeNavButton navButton" : "navButton"}>
>           Load Dicom Images
>         </Link>
>         <Link to="/viewpage" className={location.pathname === "/viewpage" ? "activeNavButton navButton" : "navButton"}>
>           Viewmodes
>         </Link>
>         <Link to="/Help" className={location.pathname === "/Help" ? "activeNavButton navButton" : "navButton"}>
>           Help
>         </Link>
>         <Link to="/Contacts" className={location.pathname === "/Contacts" ? "activeNavButton navButton" : "navButton"}>
>           Contact Info
>         </Link>
>       </div>
>     <div style={{ display: "flex", flexWrap: "wrap" }} ref={vpRef}>    
>       <div className="viewpage">
>       {viewports.map((viewportIndex) => (
>         <CornerstoneViewport
>           key={viewportIndex}
>           style={{ minWidth: "45%", height: "256px", flex: "1" }}
>           tools={tools}
>           imageIds={imageIds}
>           imageIdIndex={imageIdIndex}
>           className={activeViewportIndex === viewportIndex ? "active" : ""}
>           activeTool={activeTool}
>           setViewportActive={() => {
>             setActiveViewportIndex(viewportIndex)
>           }}
>         />
>       ))}
>       </div>
>     </div>
>     </div>
>   )
> }
> 
> export default Viewingpage

Hello @hugopereiragit and welcome to this community forum.

There is this example that might help you: https://www.cornerstonejs.org/live-examples/local.html.

The source code for that particular example can be found in packages\tools\examples\local\index.ts.

Hope this helps.