diff --git a/extensions/cornerstone-dicom-seg/src/getSopClassHandlerModule.js b/extensions/cornerstone-dicom-seg/src/getSopClassHandlerModule.js index b92da538290..b46b56e3671 100644 --- a/extensions/cornerstone-dicom-seg/src/getSopClassHandlerModule.js +++ b/extensions/cornerstone-dicom-seg/src/getSopClassHandlerModule.js @@ -1,11 +1,14 @@ -import vtkMath from '@kitware/vtk.js/Common/Core/Math'; - import { utils } from '@ohif/core'; +import { + metaData, + cache, + triggerEvent, + eventTarget, +} from '@cornerstonejs/core'; +import { adaptersSEG, Enums } from '@cornerstonejs/adapters'; import { SOPClassHandlerId } from './id'; -import dcmjs from 'dcmjs'; - -const { DicomMessage, DicomMetaDictionary } = dcmjs.data; +import { dicomlabToRGB } from './utils/dicomlabToRGB'; const sopClassUids = ['1.2.840.10008.5.1.4.1.1.66.4']; @@ -122,13 +125,12 @@ function _load(segDisplaySet, servicesManager, extensionManager, headers) { !segDisplaySet.segments || Object.keys(segDisplaySet.segments).length === 0 ) { - const segments = await _loadSegments( + await _loadSegments({ extensionManager, + servicesManager, segDisplaySet, - headers - ); - - segDisplaySet.segments = segments; + headers, + }); } const suppressEvents = true; @@ -147,143 +149,72 @@ function _load(segDisplaySet, servicesManager, extensionManager, headers) { return loadPromises[SOPInstanceUID]; } -async function _loadSegments(extensionManager, segDisplaySet, headers) { +async function _loadSegments({ + extensionManager, + servicesManager, + segDisplaySet, + headers, +}) { const utilityModule = extensionManager.getModuleEntry( '@ohif/extension-cornerstone.utilityModule.common' ); + const { segmentationService } = servicesManager.services; + const { dicomLoaderService } = utilityModule.exports; - const segArrayBuffer = await dicomLoaderService.findDicomDataPromise( + const arrayBuffer = await dicomLoaderService.findDicomDataPromise( segDisplaySet, null, headers ); - const dicomData = DicomMessage.readFile(segArrayBuffer); - const dataset = DicomMetaDictionary.naturalizeDataset(dicomData.dict); - dataset._meta = DicomMetaDictionary.namifyDataset(dicomData.meta); + const cachedReferencedVolume = cache.getVolume( + segDisplaySet.referencedVolumeId + ); - if (!Array.isArray(dataset.SegmentSequence)) { - dataset.SegmentSequence = [dataset.SegmentSequence]; + if (!cachedReferencedVolume) { + throw new Error( + 'Referenced Volume is missing for the SEG, and stack viewport SEG is not supported yet' + ); } - const segments = _getSegments(dataset); - return segments; -} + const { imageIds } = cachedReferencedVolume; -function _segmentationExists(segDisplaySet, segmentationService) { - // This should be abstracted with the CornerstoneCacheService - return segmentationService.getSegmentation( - segDisplaySet.displaySetInstanceUID - ); -} - -function _getPixelData(dataset, segments) { - let frameSize = Math.ceil((dataset.Rows * dataset.Columns) / 8); - let nextOffset = 0; - - Object.keys(segments).forEach(segmentKey => { - const segment = segments[segmentKey]; - segment.numberOfFrames = segment.functionalGroups.length; - segment.size = segment.numberOfFrames * frameSize; - segment.offset = nextOffset; - nextOffset = segment.offset + segment.size; - const packedSegment = dataset.PixelData[0].slice( - segment.offset, - nextOffset - ); + // Todo: what should be defaults here + const tolerance = 0.001; + const skipOverlapping = true; - segment.pixelData = dcmjs.data.BitArray.unpack(packedSegment); - segment.geometry = geometryFromFunctionalGroups( - dataset, - segment.functionalGroups + eventTarget.addEventListener(Enums.Events.SEGMENTATION_LOAD_PROGRESS, evt => { + const { percentComplete } = evt.detail; + segmentationService._broadcastEvent( + segmentationService.EVENTS.SEGMENT_LOADING_COMPLETE, + { + percentComplete, + } ); }); - return segments; -} - -function geometryFromFunctionalGroups(dataset, perFrame) { - let pixelMeasures = - dataset.SharedFunctionalGroupsSequence.PixelMeasuresSequence; - let planeOrientation = - dataset.SharedFunctionalGroupsSequence.PlaneOrientationSequence; - let planePosition = perFrame[0].PlanePositionSequence; // TODO: assume sorted frames! - - const geometry = {}; - - // NB: DICOM PixelSpacing is defined as Row then Column, - // unlike ImageOrientationPatient - let spacingBetweenSlices = pixelMeasures.SpacingBetweenSlices; - if (!spacingBetweenSlices) { - if (pixelMeasures.SliceThickness) { - console.log('Using SliceThickness as SpacingBetweenSlices'); - spacingBetweenSlices = pixelMeasures.SliceThickness; - } - } - geometry.spacing = [ - pixelMeasures.PixelSpacing[1], - pixelMeasures.PixelSpacing[0], - spacingBetweenSlices, - ].map(Number); - - geometry.dimensions = [dataset.Columns, dataset.Rows, perFrame.length].map( - Number + const results = await adaptersSEG.Cornerstone3D.Segmentation.generateToolState( + imageIds, + arrayBuffer, + metaData, + { skipOverlapping, tolerance, eventTarget, triggerEvent } ); - let orientation = planeOrientation.ImageOrientationPatient.map(Number); - const columnStepToPatient = orientation.slice(0, 3); - const rowStepToPatient = orientation.slice(3, 6); - geometry.planeNormal = []; - vtkMath.cross(columnStepToPatient, rowStepToPatient, geometry.planeNormal); - - let firstPosition = perFrame[0].PlanePositionSequence.ImagePositionPatient.map( - Number - ); - let lastPosition = perFrame[ - perFrame.length - 1 - ].PlanePositionSequence.ImagePositionPatient.map(Number); - geometry.sliceStep = []; - vtkMath.subtract(lastPosition, firstPosition, geometry.sliceStep); - vtkMath.normalize(geometry.sliceStep); - geometry.direction = columnStepToPatient - .concat(rowStepToPatient) - .concat(geometry.sliceStep); - geometry.origin = planePosition.ImagePositionPatient.map(Number); - - return geometry; -} - -function _getSegments(dataset) { - const segments = {}; - - dataset.SegmentSequence.forEach(segment => { - const cielab = segment.RecommendedDisplayCIELabValue; - const rgba = dcmjs.data.Colors.dicomlab2RGB(cielab).map(x => - Math.round(x * 255) - ); - - rgba.push(255); - const segmentNumber = segment.SegmentNumber; - - segments[segmentNumber] = { - color: rgba, - functionalGroups: [], - offset: null, - size: null, - pixelData: null, - label: segment.SegmentLabel, - }; + results.segMetadata.data.forEach((data, i) => { + if (i > 0) { + data.rgba = dicomlabToRGB(data.RecommendedDisplayCIELabValue); + } }); - // make a list of functional groups per segment - dataset.PerFrameFunctionalGroupsSequence.forEach(functionalGroup => { - const segmentNumber = - functionalGroup.SegmentIdentificationSequence.ReferencedSegmentNumber; - segments[segmentNumber].functionalGroups.push(functionalGroup); - }); + Object.assign(segDisplaySet, results); +} - return _getPixelData(dataset, segments); +function _segmentationExists(segDisplaySet, segmentationService) { + // This should be abstracted with the CornerstoneCacheService + return segmentationService.getSegmentation( + segDisplaySet.displaySetInstanceUID + ); } function getSopClassHandlerModule({ servicesManager, extensionManager }) { diff --git a/extensions/cornerstone-dicom-seg/src/utils/dicomlabToRGB.ts b/extensions/cornerstone-dicom-seg/src/utils/dicomlabToRGB.ts new file mode 100644 index 00000000000..a8668cf1278 --- /dev/null +++ b/extensions/cornerstone-dicom-seg/src/utils/dicomlabToRGB.ts @@ -0,0 +1,16 @@ +import dcmjs from 'dcmjs'; + +/** + * Converts a CIELAB color to an RGB color using the dcmjs library. + * @param cielab - The CIELAB color to convert. + * @returns The RGB color as an array of three integers between 0 and 255. + */ +function dicomlabToRGB(cielab: number[]): number[] { + const rgb = dcmjs.data.Colors.dicomlab2RGB(cielab).map(x => + Math.round(x * 255) + ); + + return rgb; +} + +export { dicomlabToRGB }; diff --git a/extensions/cornerstone-dicom-seg/src/viewports/OHIFCornerstoneSEGViewport.tsx b/extensions/cornerstone-dicom-seg/src/viewports/OHIFCornerstoneSEGViewport.tsx index 2f5ccb95e0f..81813bd2c76 100644 --- a/extensions/cornerstone-dicom-seg/src/viewports/OHIFCornerstoneSEGViewport.tsx +++ b/extensions/cornerstone-dicom-seg/src/viewports/OHIFCornerstoneSEGViewport.tsx @@ -317,7 +317,6 @@ function OHIFCornerstoneSEGViewport(props) { setIsHydrated(isHydrated); }; - return ( <> { - const { sopInstanceUid } = metaData.get('generalImageModule', imageId); - acc[sopInstanceUid] = index; - return acc; - }, {} as { [sopUID: string]: number }); - - const numSegments = Object.keys(segments).length; - // Note: ideally we could use the TypedArray set method, but since each - // slice can have multiple segments, we need to loop over each slice and - // set the segment value for each segment. - let overlappingSegments = false; - - const _segmentInfoUpdate = (segmentInfo, segmentIndex) => { - const { pixelData: segPixelData } = segmentInfo; - - let segmentX = 0; - let segmentY = 0; - let segmentZ = 0; - let count = 0; - - for (const [ - functionalGroupIndex, - functionalGroup, - ] of segmentInfo.functionalGroups.entries()) { - const { - ReferencedSOPInstanceUID, - } = functionalGroup.DerivationImageSequence.SourceImageSequence; - - const imageIdIndex = sopUIDImageIdIndexMap[ReferencedSOPInstanceUID]; - - if (imageIdIndex === -1) { - return; - } - - const step = rows * columns; - - // we need a faster way to get the pixel data for the current - // functional group, which we use typed array view - - const functionGroupPixelData = new Uint8Array( - segPixelData.buffer, - functionalGroupIndex * step, - step - ); + const segmentsInfo = segDisplaySet.segMetadata.data; + derivedVolumeScalarData.set(new Uint8Array(labelmapBufferArray[0])); - const functionalGroupStartIndex = imageIdIndex * step; - const functionalGroupEndIndex = (imageIdIndex + 1) * step; - - // Note: this for loop is not optimized, since DICOM SEG stores - // each segment as a separate labelmap so if there is a slice - // that has multiple segments, we will have to loop over each - // segment and we cannot use the TypedArray set method. - for ( - let i = functionalGroupStartIndex, j = 0; - i < functionalGroupEndIndex; - i++, j++ - ) { - if (functionGroupPixelData[j] !== 0) { - if (derivedVolumeScalarData[i] !== 0) { - overlappingSegments = true; - } - - derivedVolumeScalarData[i] = segmentIndex; - - // centroid calculations - segmentX += i % columns; - segmentY += Math.floor(i / columns) % rows; - segmentZ += Math.floor(i / (columns * rows)); - count++; - } - } + segmentation.segments = segmentsInfo.map((segmentInfo, segmentIndex) => { + if (segmentIndex === 0) { + return; } - // centroid calculations - const x = Math.floor(segmentX / count); - const y = Math.floor(segmentY / count); - const z = Math.floor(segmentZ / count); - + const { + SegmentedPropertyCategoryCodeSequence, + SegmentNumber, + SegmentLabel, + SegmentAlgorithmType, + SegmentAlgorithmName, + SegmentedPropertyTypeCodeSequence, + rgba, + } = segmentInfo; + + const { x, y, z } = segDisplaySet.centroids.get(segmentIndex); const centerWorld = derivedVolume.imageData.indexToWorld([x, y, z]); segmentation.cachedStats = { @@ -691,65 +630,31 @@ class SegmentationService extends PubSubService { }, }; - const numInitialized = Object.keys(segmentation.cachedStats.segmentCenter) - .length; - - // Calculate percentage completed - const percentComplete = Math.round((numInitialized / numSegments) * 100); - - this._broadcastEvent(EVENTS.SEGMENT_LOADING_COMPLETE, { - percentComplete, - numSegments: numSegments, - }); - }; - - const promiseArray = []; - - for (const segmentIndex in segments) { - const segmentInfo = segments[segmentIndex]; - - // Important: we need a non-blocking way to update the segmentation - // state, otherwise the UI will freeze and the user will not be able - // to interact with the app or progress bars will not be updated. - const promise = new Promise((resolve, reject) => { - setTimeout(() => { - _segmentInfoUpdate(segmentInfo, segmentIndex); - resolve(); - }, 0); - }); - - promiseArray.push(promise); - } - - await Promise.all(promiseArray); - - segmentation.segmentCount = Object.keys(segments).length; - segmentation.segments = [null]; // segment 0 - - Object.keys(segments).forEach(segmentIndex => { - const segmentInfo = segments[segmentIndex]; - const segIndex = Number(segmentIndex); - - segmentation.segments[segIndex] = { - label: segmentInfo.label || `Segment ${segIndex}`, - segmentIndex: Number(segmentIndex), - color: [ - segmentInfo.color[0], - segmentInfo.color[1], - segmentInfo.color[2], - ], - opacity: segmentInfo.color[3], + return { + label: SegmentLabel || `Segment ${SegmentNumber}`, + segmentIndex: Number(SegmentNumber), + category: SegmentedPropertyCategoryCodeSequence + ? SegmentedPropertyCategoryCodeSequence.CodeMeaning + : '', + type: SegmentedPropertyTypeCodeSequence + ? SegmentedPropertyTypeCodeSequence.CodeMeaning + : '', + algorithmType: SegmentAlgorithmType, + algorithmName: SegmentAlgorithmName, + color: rgba, + opacity: 255, isVisible: true, isLocked: false, }; }); + segmentation.segmentCount = segmentsInfo.length - 1; + segDisplaySet.isLoaded = true; this._broadcastEvent(EVENTS.SEGMENTATION_LOADING_COMPLETE, { segmentationId, segDisplaySet, - overlappingSegments, }); return this.addOrUpdateSegmentation(segmentation, suppressEvents); diff --git a/extensions/measurement-tracking/package.json b/extensions/measurement-tracking/package.json index 5b47cc04330..31a0dfde6ea 100644 --- a/extensions/measurement-tracking/package.json +++ b/extensions/measurement-tracking/package.json @@ -30,8 +30,8 @@ "start": "yarn run dev" }, "peerDependencies": { - "@cornerstonejs/core": "^1.7.1", - "@cornerstonejs/tools": "^1.7.1", + "@cornerstonejs/core": "^1.9.3", + "@cornerstonejs/tools": "^1.9.3", "@ohif/core": "3.7.0-beta.42", "@ohif/extension-cornerstone-dicom-sr": "3.7.0-beta.42", "@ohif/ui": "3.7.0-beta.42", diff --git a/platform/app/package.json b/platform/app/package.json index 7fbe2902c10..6ded0f987fe 100644 --- a/platform/app/package.json +++ b/platform/app/package.json @@ -30,7 +30,6 @@ "dev:dcm4chee": "cross-env NODE_ENV=development APP_CONFIG=config/local_dcm4chee.js webpack serve --config .webpack/webpack.pwa.js", "dev:static": "cross-env NODE_ENV=development APP_CONFIG=config/local_static.js webpack serve --config .webpack/webpack.pwa.js", "dev:viewer": "yarn run dev", - "preinstall": "node preinstall.js", "start": "yarn run dev", "test:e2e": "cypress open", "test:e2e:ci": "percy exec -- cypress run --config video=false --record --browser chrome --spec 'cypress/integration/visual-regression/**/*'", @@ -51,7 +50,7 @@ "@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2", "@cornerstonejs/codec-openjpeg": "^1.2.2", "@cornerstonejs/codec-openjph": "^2.4.2", - "@cornerstonejs/dicom-image-loader": "^1.7.1", + "@cornerstonejs/dicom-image-loader": "^1.9.3", "@ohif/core": "3.7.0-beta.42", "@ohif/extension-cornerstone": "3.7.0-beta.42", "@ohif/extension-cornerstone-dicom-rt": "3.7.0-beta.42", diff --git a/platform/core/package.json b/platform/core/package.json index 94a32f74d49..bcefae4b4b4 100644 --- a/platform/core/package.json +++ b/platform/core/package.json @@ -35,7 +35,7 @@ "@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2", "@cornerstonejs/codec-openjpeg": "^1.2.2", "@cornerstonejs/codec-openjph": "^2.4.2", - "@cornerstonejs/dicom-image-loader": "^1.7.1", + "@cornerstonejs/dicom-image-loader": "^1.9.3", "@ohif/ui": "3.7.0-beta.42", "cornerstone-math": "0.1.9", "dicom-parser": "^1.8.21" diff --git a/platform/core/src/classes/MetadataProvider.js b/platform/core/src/classes/MetadataProvider.js index 122306b9e05..9c09bba1f10 100644 --- a/platform/core/src/classes/MetadataProvider.js +++ b/platform/core/src/classes/MetadataProvider.js @@ -70,6 +70,11 @@ class MetadataProvider { SeriesInstanceUID, SOPInstanceUID ); + + if (!instance) { + return; + } + return ( (frameNumber && combineFrameInstance(frameNumber, instance)) || instance ); diff --git a/platform/core/src/extensions/ExtensionManager.ts b/platform/core/src/extensions/ExtensionManager.ts index c6e2972e95f..b000bb07f10 100644 --- a/platform/core/src/extensions/ExtensionManager.ts +++ b/platform/core/src/extensions/ExtensionManager.ts @@ -27,6 +27,7 @@ export type ExtensionConfiguration = Record; */ export interface ExtensionParams extends ExtensionConstructor { extensionManager: ExtensionManager; + servicesManager: ServicesManager; configuration?: ExtensionConfiguration; } @@ -43,6 +44,7 @@ export interface Extension { getViewportModule?: (p: ExtensionParams) => unknown; getUtilityModule?: (p: ExtensionParams) => unknown; getCustomizationModule?: (p: ExtensionParams) => unknown; + getSopClassHandlerModule?: (p: ExtensionParams) => unknown; onModeEnter?: () => void; onModeExit?: () => void; } diff --git a/platform/core/src/services/DisplaySetService/DisplaySetService.ts b/platform/core/src/services/DisplaySetService/DisplaySetService.ts index 5796afa9030..f95e793c635 100644 --- a/platform/core/src/services/DisplaySetService/DisplaySetService.ts +++ b/platform/core/src/services/DisplaySetService/DisplaySetService.ts @@ -1,3 +1,4 @@ +import { ExtensionManager } from '../../extensions'; import { InstanceMetadata } from '../../types'; import { PubSubService } from '../_shared/pubSubServiceInterface'; import EVENTS from './EVENTS'; @@ -47,6 +48,7 @@ export default class DisplaySetService extends PubSubService { }; public activeDisplaySets = []; + extensionManager: ExtensionManager; protected activeDisplaySetsMap = new Map(); diff --git a/platform/docs/docs/deployment/iframe.md b/platform/docs/docs/deployment/iframe.md index 4aef3b96d46..2deac3fdb8b 100644 --- a/platform/docs/docs/deployment/iframe.md +++ b/platform/docs/docs/deployment/iframe.md @@ -161,3 +161,9 @@ devServer: { } } ``` + +:::tip +Take a look at how other people have integrated OHIF in their react app + +example1: https://github.com/OHIF/Viewers/issues/3371#issuecomment-1630405255 +::: diff --git a/platform/ui/src/components/LoadingIndicatorTotalPercent/LoadingIndicatorTotalPercent.tsx b/platform/ui/src/components/LoadingIndicatorTotalPercent/LoadingIndicatorTotalPercent.tsx index 4a649e45362..33082af2a1f 100644 --- a/platform/ui/src/components/LoadingIndicatorTotalPercent/LoadingIndicatorTotalPercent.tsx +++ b/platform/ui/src/components/LoadingIndicatorTotalPercent/LoadingIndicatorTotalPercent.tsx @@ -21,26 +21,23 @@ function LoadingIndicatorTotalPercent({ loadingText = 'Loading...', targetText = 'segments', }: Props): JSX.Element { - percentComplete = percentComplete !== null ? percentComplete : null; - - const progress = percentComplete !== null ? percentComplete : null; + const progress = percentComplete; const totalNumbersText = totalNumbers !== null ? `${totalNumbers}` : ''; const numTargetsLoadedText = percentComplete !== null ? Math.floor((percentComplete * totalNumbers) / 100) : ''; - const textBlock = !totalNumbers ? ( -
{loadingText}
- ) : ( -
-
Loaded
-
{numTargetsLoadedText}
-
of
-
{totalNumbersText}
-
{targetText}
-
- ); + const textBlock = + !totalNumbers && percentComplete === null ? ( +
{loadingText}
+ ) : !totalNumbers && percentComplete !== null ? ( +
Loaded {percentComplete}%
+ ) : ( +
+ Loaded {numTargetsLoadedText} of {totalNumbersText} {targetText} +
+ ); return ( - {thickness} + {thicknessUnits + ? `${thickness}${thicknessUnits}` + : `${thickness}`}
@@ -136,6 +138,7 @@ PatientInfo.propTypes = { patientAge: PropTypes.string, MRN: PropTypes.string, thickness: PropTypes.string, + thicknessUnits: PropTypes.string, spacing: PropTypes.string, scanner: PropTypes.string, isOpen: PropTypes.bool, diff --git a/platform/ui/src/components/ViewportActionBar/ViewportActionBar.tsx b/platform/ui/src/components/ViewportActionBar/ViewportActionBar.tsx index ec07610977f..c4124522cb4 100644 --- a/platform/ui/src/components/ViewportActionBar/ViewportActionBar.tsx +++ b/platform/ui/src/components/ViewportActionBar/ViewportActionBar.tsx @@ -34,6 +34,7 @@ const ViewportActionBar = ({ patientAge, MRN, thickness, + thicknessUnits, spacing, scanner, } = patientInformation; @@ -169,6 +170,7 @@ const ViewportActionBar = ({ patientAge={patientAge} MRN={MRN} thickness={thickness} + thicknessUnits={thicknessUnits} spacing={spacing} scanner={scanner} /> @@ -192,6 +194,7 @@ ViewportActionBar.propTypes = { patientAge: PropTypes.string.isRequired, MRN: PropTypes.string.isRequired, thickness: PropTypes.string.isRequired, + thicknessUnits: PropTypes.string.isRequired, spacing: PropTypes.string.isRequired, scanner: PropTypes.string.isRequired, }), diff --git a/yarn.lock b/yarn.lock index 144d51c9cff..efb420662cd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1321,9 +1321,9 @@ regenerator-runtime "^0.13.11" "@babel/runtime@7.17.9", "@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.3", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.17.8", "@babel/runtime@^7.18.6", "@babel/runtime@^7.20.13", "@babel/runtime@^7.20.6", "@babel/runtime@^7.20.7", "@babel/runtime@^7.22.6", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.4", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2": - version "7.22.6" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.6.tgz#57d64b9ae3cff1d67eb067ae117dac087f5bd438" - integrity sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ== + version "7.22.3" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.3.tgz#0a7fce51d43adbf0f7b517a71f4c3aaca92ebcbb" + integrity sha512-XsDuspWKLUsxwCp6r7EhsExHtYfbe5oAGQ19kqngTdCPUoPQzOPdUbD/pB9PJiwb2ptYKQDjSJT3R6dC+EPqfQ== dependencies: regenerator-runtime "^0.13.11" @@ -1376,13 +1376,14 @@ resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== -"@cornerstonejs/adapters@^1.7.1": - version "1.7.1" - resolved "https://registry.yarnpkg.com/@cornerstonejs/adapters/-/adapters-1.7.1.tgz#5ae8b510791f5817420ade4b5637f9e84a8ada52" - integrity sha512-iwowMUVoNKWZ3PTmYSjnZ2vDThR+OUkvIsSB913A1YhPCl+FVv2Y0JLdueFCYKlTFLnzFa8FOlFwzAOI+AAB+Q== +"@cornerstonejs/adapters@^1.9.3": + version "1.9.3" + resolved "https://registry.yarnpkg.com/@cornerstonejs/adapters/-/adapters-1.9.3.tgz#b1031e26af175ac15c3c975aff89f51c214ec092" + integrity sha512-bjpUq78yupE3+z5qNAS7j27OgCn1BAJQKwcQNY+PBUzTojwg2KpMpG69I+CucSCAxHKDv4waQy4hEyNaiI5JAA== dependencies: "@babel/runtime-corejs2" "^7.17.8" - dcmjs "^0.29.5" + buffer "^6.0.3" + dcmjs "^0.29.8" gl-matrix "^3.4.3" lodash.clonedeep "^4.5.0" ndarray "^1.0.19" @@ -1427,43 +1428,43 @@ resolved "https://registry.yarnpkg.com/@cornerstonejs/codec-openjph/-/codec-openjph-2.4.2.tgz#e96721d56f6ec96f7f95c16321d88cc8467d8d81" integrity sha512-lgdvBvvNezleY+4pIe2ceUsJzlZe/0PipdeubQ3vZZOz3xxtHHMR1XFCl4fgd8gosR8COHuD7h6q+MwgrwBsng== -"@cornerstonejs/core@^1.7.1": - version "1.7.1" - resolved "https://registry.yarnpkg.com/@cornerstonejs/core/-/core-1.7.1.tgz#38c2fa24cc166b15088a0f8d220ae33e9a80cb7e" - integrity sha512-XS44HcRwXJ81QqEnOjbpstLCrhApzNIvBuV4UM1+qhvUn0fg6LrXEkR/cT4xQ0RhHB9oq+0LPsfm9/X2xxWZAA== +"@cornerstonejs/core@^1.9.3": + version "1.9.3" + resolved "https://registry.yarnpkg.com/@cornerstonejs/core/-/core-1.9.3.tgz#43c04b5c2a929e1f2ffc71d71aa2311dea2b1e7d" + integrity sha512-TMgxFe23Rur0k3ISDh0JGkQ6x2xCYFnqON68A+Eovxc7g/sHUZ0tbzXiTd+IaVpuRsaDxspb0fwklPISKTJDuA== dependencies: "@kitware/vtk.js" "27.3.1" detect-gpu "^5.0.22" gl-matrix "^3.4.3" lodash.clonedeep "4.5.0" -"@cornerstonejs/dicom-image-loader@^1.7.1": - version "1.7.1" - resolved "https://registry.yarnpkg.com/@cornerstonejs/dicom-image-loader/-/dicom-image-loader-1.7.1.tgz#c5ee643bd1c846c1ca7c536f6db3ae26050353fd" - integrity sha512-U15NsCdjKkU6OKKWvRs6IwBxRqAudE2vZh+fwAWB9tmyjZCHnRs0KgscOVoYQvR5EV7f1gz7777Iz/u8tnSoFQ== +"@cornerstonejs/dicom-image-loader@^1.9.3": + version "1.9.3" + resolved "https://registry.yarnpkg.com/@cornerstonejs/dicom-image-loader/-/dicom-image-loader-1.9.3.tgz#6ec07e8f22ba20c78cab930a1396effc1f86885e" + integrity sha512-+JRiI5hb9Cuo7yRGg3DzqgXTmNUMn9DAI1ASh721mbqJcPymHBDs+QTfF2bXyAnh4Ijxr+WfCEUSBm4PRPvrAw== dependencies: "@cornerstonejs/codec-charls" "^1.2.3" "@cornerstonejs/codec-libjpeg-turbo-8bit" "^1.2.2" "@cornerstonejs/codec-openjpeg" "^1.2.2" "@cornerstonejs/codec-openjph" "^2.4.2" - "@cornerstonejs/core" "^1.7.1" + "@cornerstonejs/core" "^1.9.3" dicom-parser "^1.8.9" pako "^2.0.4" uuid "^9.0.0" -"@cornerstonejs/streaming-image-volume-loader@^1.7.1": - version "1.7.1" - resolved "https://registry.yarnpkg.com/@cornerstonejs/streaming-image-volume-loader/-/streaming-image-volume-loader-1.7.1.tgz#1102cde7136f4804c21b665b6429210545a79087" - integrity sha512-eIILqRpWodUVX4HgJbWlZhVebsz4gLxZaOtErOvL/knSK3zyb/D+Rsz8RjWbMJsixHp+gQ/Q51q/FYab/RvJrw== +"@cornerstonejs/streaming-image-volume-loader@^1.9.3": + version "1.9.3" + resolved "https://registry.yarnpkg.com/@cornerstonejs/streaming-image-volume-loader/-/streaming-image-volume-loader-1.9.3.tgz#1772273bfd59f7f470ba254d9463c2d1f9c22359" + integrity sha512-xD1+ZNrYa1FQTgieG11d6jYnuZFH2zpDzg5eigFeZx9e8Vsu9rO1lpkwVWUw1Cf3qhqmsG9PA+BxHQm3ACjwTg== dependencies: - "@cornerstonejs/core" "^1.7.1" + "@cornerstonejs/core" "^1.9.3" -"@cornerstonejs/tools@^1.7.1": - version "1.7.1" - resolved "https://registry.yarnpkg.com/@cornerstonejs/tools/-/tools-1.7.1.tgz#7cd589db556ba8a2139fcdaf01b84e03d4b78d2e" - integrity sha512-iulzSXInFlcsLTWsn4xCF+dpZEwSWf/UjZBLmVNfTA262bncmE083cn57VEB9mRuFN+doA50/8UJi7uNew+Q5Q== +"@cornerstonejs/tools@^1.9.3": + version "1.9.3" + resolved "https://registry.yarnpkg.com/@cornerstonejs/tools/-/tools-1.9.3.tgz#40e967c4bc275b4bf4d38f6c26d3a979779a632b" + integrity sha512-mesMJi8L0JHebYy7F3+VE+6zRwkv9ZaYw4cwplguTgOq7s7xmINVHomIVkffHUQeUPhwPVmxbjIqeW6O5MkXeg== dependencies: - "@cornerstonejs/core" "^1.7.1" + "@cornerstonejs/core" "^1.9.3" lodash.clonedeep "4.5.0" lodash.get "^4.4.2" @@ -8219,7 +8220,7 @@ dcmjs@^0.27: loglevelnext "^3.0.1" ndarray "^1.0.19" -dcmjs@^0.29.5: +dcmjs@^0.29.5, dcmjs@^0.29.8: version "0.29.8" resolved "https://registry.yarnpkg.com/dcmjs/-/dcmjs-0.29.8.tgz#3daa5224f8e75b2e5b069590bef26a272741fa44" integrity sha512-Y0/KZAmT1siVo7eH3KK4ZflEbNi61soUpD0N7lsXMVVJQ6IZkHlaSzb9DtqnEpMs7RJDfvZGr1uXpv1vBBIypQ==