diff --git a/extensions/cornerstone/package.json b/extensions/cornerstone/package.json
index b33db6600..4dd657d40 100644
--- a/extensions/cornerstone/package.json
+++ b/extensions/cornerstone/package.json
@@ -34,8 +34,8 @@
"cornerstone-core": "^2.3.0",
"cornerstone-math": "^0.1.8",
"cornerstone-tools": "4.15.1",
- "cornerstone-wado-image-loader": "^3.1.0",
"dcmjs": "^0.12.3",
+ "cornerstone-wado-image-loader": "^3.1.2",
"dicom-parser": "^1.8.3",
"hammerjs": "^2.0.8",
"prop-types": "^15.6.2",
diff --git a/extensions/cornerstone/src/commandsModule.js b/extensions/cornerstone/src/commandsModule.js
index 99d93cc30..74c0d56f2 100644
--- a/extensions/cornerstone/src/commandsModule.js
+++ b/extensions/cornerstone/src/commandsModule.js
@@ -12,6 +12,9 @@ const { setViewportSpecificData } = OHIF.redux.actions;
const commandsModule = ({ servicesManager }) => {
const actions = {
+ getCornerstoneLibraries: () => {
+ return { cornerstone, cornerstoneTools };
+ },
rotateViewport: ({ viewports, rotation }) => {
const enabledElement = getEnabledElement(viewports.activeViewportIndex);
@@ -262,23 +265,28 @@ const commandsModule = ({ servicesManager }) => {
StudyInstanceUID,
SOPInstanceUID,
frameIndex,
- activeViewportIndex
+ activeViewportIndex,
}) => {
const study = studyMetadataManager.get(StudyInstanceUID);
const displaySet = study.findDisplaySet(ds => {
- return ds.images && ds.images.find(i => i.getSOPInstanceUID() === SOPInstanceUID)
+ return (
+ ds.images &&
+ ds.images.find(i => i.getSOPInstanceUID() === SOPInstanceUID)
+ );
});
displaySet.SOPInstanceUID = SOPInstanceUID;
displaySet.frameIndex = frameIndex;
- window.store.dispatch(setViewportSpecificData(activeViewportIndex, displaySet));
+ window.store.dispatch(
+ setViewportSpecificData(activeViewportIndex, displaySet)
+ );
cornerstone.getEnabledElements().forEach(enabledElement => {
cornerstone.updateImage(enabledElement.element);
});
- }
+ },
};
const definitions = {
@@ -287,6 +295,12 @@ const commandsModule = ({ servicesManager }) => {
storeContexts: [],
options: {},
},
+ getCornerstoneLibraries: {
+ commandFn: actions.getCornerstoneLibraries,
+ storeContexts: [],
+ options: {},
+ context: 'VIEWER',
+ },
getNearbyToolData: {
commandFn: actions.getNearbyToolData,
storeContexts: [],
diff --git a/extensions/cornerstone/src/init.js b/extensions/cornerstone/src/init.js
index 27e962b80..4002ca9b2 100644
--- a/extensions/cornerstone/src/init.js
+++ b/extensions/cornerstone/src/init.js
@@ -4,6 +4,7 @@ import cornerstone from 'cornerstone-core';
import csTools from 'cornerstone-tools';
import merge from 'lodash.merge';
import initCornerstoneTools from './initCornerstoneTools.js';
+import initWADOImageLoader from './initWADOImageLoader.js';
import measurementServiceMappingsFactory from './utils/measurementServiceMappings/measurementServiceMappingsFactory';
/**
diff --git a/extensions/cornerstone/src/initWADOImageLoader.js b/extensions/cornerstone/src/initWADOImageLoader.js
new file mode 100644
index 000000000..c33dded36
--- /dev/null
+++ b/extensions/cornerstone/src/initWADOImageLoader.js
@@ -0,0 +1,18 @@
+import cornerstone from 'cornerstone-core';
+import cornerstoneWADOImageLoader from 'cornerstone-wado-image-loader';
+import dicomParser from 'dicom-parser';
+
+//import { initWebWorkers } from './utils/index.js';
+
+cornerstoneWADOImageLoader.external.cornerstone = cornerstone;
+cornerstoneWADOImageLoader.external.dicomParser = dicomParser;
+
+cornerstoneWADOImageLoader.configure({
+ beforeSend: function(xhr) {
+ /*const headers = OHIF.DICOMWeb.getAuthorizationHeader();
+
+ if (headers.Authorization) {
+ xhr.setRequestHeader('Authorization', headers.Authorization);
+ }*/
+ },
+});
diff --git a/extensions/default/src/ViewerLayout/index.jsx b/extensions/default/src/ViewerLayout/index.jsx
index b163d7d94..6bec8f7a2 100644
--- a/extensions/default/src/ViewerLayout/index.jsx
+++ b/extensions/default/src/ViewerLayout/index.jsx
@@ -31,7 +31,7 @@ function ViewerLayout({
const getPanelData = id => {
const entry = extensionManager.getModuleEntry(id);
// TODO, not sure why sidepanel content has to be JSX, and not a children prop?
- const content = entry.component({ extensionManager });
+ const content = entry.component;
return {
iconName: entry.iconName,
diff --git a/extensions/default/src/getPanelModule.js b/extensions/default/src/getPanelModule.js
index 392392bd9..9051116f8 100644
--- a/extensions/default/src/getPanelModule.js
+++ b/extensions/default/src/getPanelModule.js
@@ -7,37 +7,86 @@ import {
displaySetManager,
} from '@ohif/core';
-function StudyBrowserPanel({ extensionManager }) {
- // TODO: need to check how this is intended to be passed in
- const dataSource = extensionManager.dataSourceMap.dicomweb[0];
+// Create map in local state from displaySetInstanceUids to thumbnails
+// Get thumbnail imageId from displaySet
+// When displaySetInstanceUids change, initiate async render into canvas
+// Get image data-uri from canvas offscreen
+// Set image data-uri into state (NOTE: This will probably end up in the fucking browser cache, NEED to find a way to prevent that from happening)
+// state triggers rerender
+//
+// TODO:
+// - No loading UI exists yet
+// - cancel promises when component is destroyed
+// - show errors in UI for thumbnails if promise fails
+function getImageSrc(imageId, { cornerstone }) {
+ // TODO: Switch to async/await when it stops failing
+ return new Promise((resolve, reject) => {
+ cornerstone.loadAndCacheImage(imageId).then(image => {
+ const canvas = document.createElement('canvas');
+ cornerstone.renderToCanvas(canvas, image);
+
+ resolve(canvas.toDataURL());
+ });
+ });
+}
+
+function StudyBrowserPanel({ getDataSources, commandsManager }) {
const viewModel = useViewModel();
+ const dataSource = getDataSources('dicomweb')[0];
+ const [studyData, setStudyData] = useState([]);
+ const [thumbnailImageSrcMap, setThumbnailImageSrcMap] = useState(new Map());
+ const updateThumbnailMap = (k, v) => {
+ setThumbnailImageSrcMap(thumbnailImageSrcMap.set(k, v));
+ };
+
+ useEffect(() => {
+ const command = commandsManager.getCommand(
+ 'getCornerstoneLibraries',
+ 'VIEWER'
+ );
+
+ if (!command) {
+ throw new Error('Required command not found');
+ }
+
+ const { cornerstone, cornerstoneTools } = command.commandFn();
+
+ if (!viewModel.displaySetInstanceUids.length) {
+ return;
+ }
+
+ viewModel.displaySetInstanceUids.forEach(uid => {
+ const imageIds = dataSource.getImageIdsForDisplaySet(uid);
+ const imageId = imageIds[0];
+
+ getImageSrc(imageId, { cornerstone }).then(imageSrc => {
+ updateThumbnailMap(uid, imageSrc);
+ });
+ });
+ }, [viewModel.displaySetInstanceUids]);
+
// TODO
const viewportData = []; //useViewportGrid();
const seriesTracking = {}; //useSeriesTracking();
- const [studyData, setStudyData] = useState([]);
-
- console.log(viewModel);
-
const displaySets = viewModel.displaySetInstanceUids.map(
displaySetManager.getDisplaySetByUID
);
- console.log(displaySets);
-
- if (!displaySets.length) {
- return;
- }
-
// TODO:
// - Put this in something so it only runs once
// - Have update the query update the dicom data store at the study level and then have this component use the data in the view model
useEffect(() => {
+ if (!viewModel.displaySetInstanceUids.length) {
+ return;
+ }
+
const dSets = viewModel.displaySetInstanceUids.map(
displaySetManager.getDisplaySetByUID
);
+
const aDisplaySet = dSets[0];
const firstStudy = dicomMetadataStore.getStudy(
aDisplaySet.StudyInstanceUID
@@ -74,6 +123,7 @@ function StudyBrowserPanel({ extensionManager }) {
modality: ds.Modality,
date: ds.SeriesDate,
numInstances: ds.numImageFrames,
+ //imageSrc,
};
const displaySetViewportData = viewportData.find(
@@ -203,21 +253,30 @@ function StudyBrowserPanel({ extensionManager }) {
return ;
}
-function getPanelModule() {
+function getPanelModule({ getDataSources, commandsManager }) {
+ const wrappedStudyBrowserPanel = () => {
+ return (
+
+ );
+ };
+
return [
{
name: 'seriesList',
iconName: 'group-layers',
iconLabel: 'Studies',
label: 'Studies',
- component: StudyBrowserPanel,
+ component: wrappedStudyBrowserPanel,
},
{
name: 'measure',
iconName: 'list-bullets',
iconLabel: 'Measure',
label: 'Measurements',
- component: StudyBrowserPanel,
+ component: wrappedStudyBrowserPanel,
},
];
}
diff --git a/extensions/vtk/package.json b/extensions/vtk/package.json
index cd87400dd..422d61c6f 100644
--- a/extensions/vtk/package.json
+++ b/extensions/vtk/package.json
@@ -28,13 +28,12 @@
"start": "yarn run dev"
},
"peerDependencies": {
- "@ohif/core": "^0.50.0",
- "@ohif/i18n": "^0.50.0",
- "@ohif/ui": "^0.50.0",
- "cornerstone-core": "^2.2.8",
- "cornerstone-tools": "4.15.1",
- "cornerstone-wado-image-loader": "^3.1.0",
- "dcmjs": "^0.12.2",
+ "@ohif/core": "^2.5.1",
+ "@ohif/i18n": "^0.52.6",
+ "@ohif/ui": "^2.0.0",
+ "cornerstone-core": "^2.3.0",
+ "cornerstone-wado-image-loader": "^3.1.2",
+ "dcmjs": "0.12.2",
"dicom-parser": "^1.8.3",
"i18next": "^17.0.3",
"i18next-browser-languagedetector": "^3.0.1",
@@ -56,9 +55,10 @@
},
"devDependencies": {
"@ohif/core": "^2.9.6",
- "@ohif/ui": "^1.4.4",
"cornerstone-tools": "4.15.1",
- "cornerstone-wado-image-loader": "^3.1.0",
+ "@ohif/ui": "^2.0.0",
+ "cornerstone-core": "^2.3.0",
+ "cornerstone-wado-image-loader": "^3.1.2",
"dicom-parser": "^1.8.3",
"gh-pages": "^2.0.1",
"i18next": "^17.0.3",
diff --git a/platform/core/package.json b/platform/core/package.json
index 115f1de21..fa97ec8da 100644
--- a/platform/core/package.json
+++ b/platform/core/package.json
@@ -32,7 +32,7 @@
"peerDependencies": {
"cornerstone-core": "^2.3.0",
"cornerstone-tools": "^4.12.0",
- "cornerstone-wado-image-loader": "^3.0.0",
+ "cornerstone-wado-image-loader": "^3.1.2",
"dicom-parser": "^1.8.3"
},
"dependencies": {
diff --git a/platform/core/src/extensions/ExtensionManager.js b/platform/core/src/extensions/ExtensionManager.js
index 062738f83..954a50ed1 100644
--- a/platform/core/src/extensions/ExtensionManager.js
+++ b/platform/core/src/extensions/ExtensionManager.js
@@ -177,6 +177,7 @@ export default class ExtensionManager {
try {
const extensionModule = getModuleFn({
+ getDataSources: this.getDataSources,
servicesManager: this._servicesManager,
commandsManager: this._commandsManager,
appConfig: this._appConfig,
diff --git a/platform/ui/src/components/SidePanel/SidePanel.jsx b/platform/ui/src/components/SidePanel/SidePanel.jsx
index 78eb036ef..cc49896f8 100644
--- a/platform/ui/src/components/SidePanel/SidePanel.jsx
+++ b/platform/ui/src/components/SidePanel/SidePanel.jsx
@@ -141,7 +141,7 @@ const SidePanel = ({
- {childComponent.content}
+
) : (
{getPanelButtons()}
diff --git a/platform/ui/src/components/ThumbnailList/ThumbnailList.jsx b/platform/ui/src/components/ThumbnailList/ThumbnailList.jsx
index 375ecbd91..8007ea8fb 100644
--- a/platform/ui/src/components/ThumbnailList/ThumbnailList.jsx
+++ b/platform/ui/src/components/ThumbnailList/ThumbnailList.jsx
@@ -18,6 +18,8 @@ const ThumbnailList = ({ thumbnails }) => {
viewportIdentificator,
isTracked,
isActive,
+ imageSrc,
+ imageAltText,
}) => {
switch (componentType) {
case 'thumbnail':
@@ -27,6 +29,9 @@ const ThumbnailList = ({ thumbnails }) => {
description={description}
seriesNumber={seriesNumber}
numInstances={numInstances}
+ imageSrc={imageSrc}
+ imageAltText={imageAltText}
+ viewportIdentificator={viewportIdentificator}
isActive={isActive}
onClick={() => {}}
/>
@@ -48,6 +53,8 @@ const ThumbnailList = ({ thumbnails }) => {
description={description}
seriesNumber={seriesNumber}
numInstances={numInstances}
+ imageSrc={imageSrc}
+ imageAltText={imageAltText}
viewportIdentificator={viewportIdentificator}
isTracked={isTracked}
isActive={isActive}
diff --git a/platform/viewer/package.json b/platform/viewer/package.json
index bc6dd2ccd..79e2ed2cf 100644
--- a/platform/viewer/package.json
+++ b/platform/viewer/package.json
@@ -67,8 +67,8 @@
"core-js": "^3.2.1",
"cornerstone-math": "^0.1.8",
"cornerstone-tools": "4.15.1",
- "cornerstone-wado-image-loader": "^3.1.0",
"dcmjs": "^0.12.2",
+ "cornerstone-wado-image-loader": "^3.1.2",
"dicom-parser": "^1.8.3",
"dicomweb-client": "^0.4.4",
"dotenv-webpack": "^1.7.0",
diff --git a/yarn.lock b/yarn.lock
index 5f114ffea..0637cef56 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -5791,10 +5791,10 @@ cornerstone-tools@^4.12.0:
"@babel/runtime" "7.1.2"
cornerstone-math "0.1.7"
-cornerstone-wado-image-loader@^3.0.0:
- version "3.0.6"
- resolved "https://registry.yarnpkg.com/cornerstone-wado-image-loader/-/cornerstone-wado-image-loader-3.0.6.tgz#7b2be91f8f658de3a7474e029aa8314a35725132"
- integrity sha512-1luWOh1GzkboZ3uxfu4T8vh7K9nlDiiEbQ4dYIY9oobRZVZQbQiLT8wEZPbb4JTUe7UWJISHPCNgtAU8UE9DNw==
+cornerstone-wado-image-loader@^3.1.2:
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/cornerstone-wado-image-loader/-/cornerstone-wado-image-loader-3.1.2.tgz#5113c317938510670061d11d05deb70266e4a35e"
+ integrity sha512-cnDHrsa2GREqdMb9pjsoHgue+suHkDyuS/W0R8ZVD1lr+LQdv56dVM8oK9n7yOeorA4/IXG8630IL7uHdCHAQA==
dependencies:
dicom-parser "^1.8.3"
pako "^1.0.10"