From 9bf24d6dc58ed8f65c90899a17c11044b792cf40 Mon Sep 17 00:00:00 2001 From: Alireza Date: Tue, 17 Dec 2024 12:34:13 -0500 Subject: [PATCH] fix(seg): jump to the first slice in SEG and RT that has data (#4605) --- .../viewports/OHIFCornerstonePMAPViewport.tsx | 1 + .../cornerstone-dicom-rt/src/loadRTStruct.js | 10 +++++- .../viewports/OHIFCornerstoneRTViewport.tsx | 20 ++++++++--- .../viewports/OHIFCornerstoneSEGViewport.tsx | 13 +++++++ .../OHIFCornerstoneSRMeasurementViewport.tsx | 32 ++++++----------- extensions/cornerstone/src/hps/frameView.ts | 2 +- .../SegmentationService.ts | 24 ++++++++++++- .../CornerstoneViewportService.ts | 36 ++++++++++++++----- .../default/src/getHangingProtocolModule.js | 2 +- .../default/src/hangingprotocols/hpCompare.ts | 4 +-- .../default/src/hangingprotocols/hpMNGrid.ts | 2 +- .../default/src/hangingprotocols/hpScale.ts | 2 +- extensions/test-extension/src/hpTestSwitch.ts | 2 +- platform/app/public/config/local_orthanc.js | 1 + yarn.lock | 32 ++++++++--------- 15 files changed, 123 insertions(+), 60 deletions(-) diff --git a/extensions/cornerstone-dicom-pmap/src/viewports/OHIFCornerstonePMAPViewport.tsx b/extensions/cornerstone-dicom-pmap/src/viewports/OHIFCornerstonePMAPViewport.tsx index 2133e96dd..959d8dbfe 100644 --- a/extensions/cornerstone-dicom-pmap/src/viewports/OHIFCornerstonePMAPViewport.tsx +++ b/extensions/cornerstone-dicom-pmap/src/viewports/OHIFCornerstonePMAPViewport.tsx @@ -97,6 +97,7 @@ function OHIFCornerstonePMAPViewport(props: withAppTypes) { viewportType: 'volume', orientation: viewportOptions.orientation, viewportId: viewportOptions.viewportId, + presentationIds: viewportOptions.presentationIds, }} displaySetOptions={[{}, pmapDisplaySetOptions]} > diff --git a/extensions/cornerstone-dicom-rt/src/loadRTStruct.js b/extensions/cornerstone-dicom-rt/src/loadRTStruct.js index 10d9cc99f..0e9ab3841 100644 --- a/extensions/cornerstone-dicom-rt/src/loadRTStruct.js +++ b/extensions/cornerstone-dicom-rt/src/loadRTStruct.js @@ -126,6 +126,7 @@ export default async function loadRTStruct(extensionManager, rtStructDisplaySet, SeriesInstanceUID: instance.SeriesInstanceUID, ROIContours: [], visible: true, + ReferencedSOPInstanceUIDsSet: new Set(), }; for (let i = 0; i < ROIContourSequence.length; i++) { @@ -142,7 +143,8 @@ export default async function loadRTStruct(extensionManager, rtStructDisplaySet, const contourPoints = []; for (let c = 0; c < ContourSequenceArray.length; c++) { - const { ContourData, NumberOfContourPoints, ContourGeometricType } = ContourSequenceArray[c]; + const { ContourData, NumberOfContourPoints, ContourGeometricType, ContourImageSequence } = + ContourSequenceArray[c]; let isSupported = false; @@ -172,6 +174,12 @@ export default async function loadRTStruct(extensionManager, rtStructDisplaySet, type: ContourGeometricType, isSupported, }); + + if (ContourImageSequence?.ReferencedSOPInstanceUID) { + structureSet.ReferencedSOPInstanceUIDsSet.add( + ContourImageSequence?.ReferencedSOPInstanceUID + ); + } } _setROIContourMetadata( diff --git a/extensions/cornerstone-dicom-rt/src/viewports/OHIFCornerstoneRTViewport.tsx b/extensions/cornerstone-dicom-rt/src/viewports/OHIFCornerstoneRTViewport.tsx index 1c4a9e0e9..662541ff1 100644 --- a/extensions/cornerstone-dicom-rt/src/viewports/OHIFCornerstoneRTViewport.tsx +++ b/extensions/cornerstone-dicom-rt/src/viewports/OHIFCornerstoneRTViewport.tsx @@ -6,7 +6,7 @@ import promptHydrateRT from '../utils/promptHydrateRT'; import _getStatusComponent from './_getStatusComponent'; import createRTToolGroupAndAddTools from '../utils/initRTToolGroup'; -import { SegmentationRepresentations } from '@cornerstonejs/tools/enums'; +import { usePositionPresentationStore } from '@ohif/extension-cornerstone'; const RT_TOOLGROUP_BASE_NAME = 'RTToolGroup'; @@ -43,8 +43,8 @@ function OHIFCornerstoneRTViewport(props: withAppTypes) { const [viewportGrid, viewportGridService] = useViewportGrid(); // States - const [isToolGroupCreated, setToolGroupCreated] = useState(false); const [selectedSegment, setSelectedSegment] = useState(1); + const { setPositionPresentation } = usePositionPresentationStore(); // Hydration means that the RT is opened and segments are loaded into the // segmentation panel, and RT is also rendered on any viewport that is in the @@ -123,6 +123,7 @@ function OHIFCornerstoneRTViewport(props: withAppTypes) { toolGroupId: toolGroupId, orientation: viewportOptions.orientation, viewportId: viewportOptions.viewportId, + presentationIds: viewportOptions.presentationIds, }} onElementEnabled={evt => { props.onElementEnabled?.(evt); @@ -185,6 +186,19 @@ function OHIFCornerstoneRTViewport(props: withAppTypes) { setRtIsLoading(false); } + if (rtDisplaySet?.firstSegmentedSliceImageId && viewportOptions?.presentationIds) { + const { firstSegmentedSliceImageId } = rtDisplaySet; + const { presentationIds } = viewportOptions; + + setPositionPresentation(presentationIds.positionPresentationId, { + viewportType: 'stack', + viewReference: { + referencedImageId: firstSegmentedSliceImageId, + }, + viewPresentation: {}, + }); + } + if (evt.overlappingSegments) { uiNotificationService.show({ title: 'Overlapping Segments', @@ -247,8 +261,6 @@ function OHIFCornerstoneRTViewport(props: withAppTypes) { toolGroup = createRTToolGroupAndAddTools(toolGroupService, customizationService, toolGroupId); - setToolGroupCreated(true); - return () => { // remove the segmentation representations if seg displayset changed segmentationService.removeSegmentationRepresentations(viewportId); diff --git a/extensions/cornerstone-dicom-seg/src/viewports/OHIFCornerstoneSEGViewport.tsx b/extensions/cornerstone-dicom-seg/src/viewports/OHIFCornerstoneSEGViewport.tsx index 21dff244f..340afad16 100644 --- a/extensions/cornerstone-dicom-seg/src/viewports/OHIFCornerstoneSEGViewport.tsx +++ b/extensions/cornerstone-dicom-seg/src/viewports/OHIFCornerstoneSEGViewport.tsx @@ -4,6 +4,7 @@ import { LoadingIndicatorTotalPercent, useViewportGrid, ViewportActionArrows } f import createSEGToolGroupAndAddTools from '../utils/initSEGToolGroup'; import promptHydrateSEG from '../utils/promptHydrateSEG'; import _getStatusComponent from './_getStatusComponent'; +import { usePositionPresentationStore } from '@ohif/extension-cornerstone'; import { SegmentationRepresentations } from '@cornerstonejs/tools/enums'; const SEG_TOOLGROUP_BASE_NAME = 'SEGToolGroup'; @@ -41,6 +42,7 @@ function OHIFCornerstoneSEGViewport(props: withAppTypes) { // States const [selectedSegment, setSelectedSegment] = useState(1); + const { setPositionPresentation } = usePositionPresentationStore(); // Hydration means that the SEG is opened and segments are loaded into the // segmentation panel, and SEG is also rendered on any viewport that is in the @@ -198,6 +200,17 @@ function OHIFCornerstoneSEGViewport(props: withAppTypes) { if (evt.segDisplaySet.displaySetInstanceUID === segDisplaySet.displaySetInstanceUID) { setSegIsLoading(false); } + + if (segDisplaySet?.firstSegmentedSliceImageId && viewportOptions?.presentationIds) { + const { firstSegmentedSliceImageId } = segDisplaySet; + const { presentationIds } = viewportOptions; + + setPositionPresentation(presentationIds.positionPresentationId, { + viewReference: { + referencedImageId: firstSegmentedSliceImageId, + }, + }); + } } ); diff --git a/extensions/cornerstone-dicom-sr/src/components/OHIFCornerstoneSRMeasurementViewport.tsx b/extensions/cornerstone-dicom-sr/src/components/OHIFCornerstoneSRMeasurementViewport.tsx index c67eb64f1..5aef2c508 100644 --- a/extensions/cornerstone-dicom-sr/src/components/OHIFCornerstoneSRMeasurementViewport.tsx +++ b/extensions/cornerstone-dicom-sr/src/components/OHIFCornerstoneSRMeasurementViewport.tsx @@ -16,22 +16,13 @@ const MEASUREMENT_TRACKING_EXTENSION_ID = '@ohif/extension-measurement-tracking' const SR_TOOLGROUP_BASE_NAME = 'SRToolGroup'; function OHIFCornerstoneSRMeasurementViewport(props: withAppTypes) { - const { - children, - dataSource, - displaySets, - viewportOptions, - servicesManager, - extensionManager, - } = props; + const { children, dataSource, displaySets, viewportOptions, servicesManager, extensionManager } = + props; const [appConfig] = useAppConfig(); - const { - displaySetService, - measurementService, - viewportActionCornersService, - } = servicesManager.services; + const { displaySetService, measurementService, viewportActionCornersService } = + servicesManager.services; const viewportId = viewportOptions.viewportId; @@ -44,7 +35,6 @@ function OHIFCornerstoneSRMeasurementViewport(props: withAppTypes) { const { setPositionPresentation } = usePositionPresentationStore(); - const [viewportGrid, viewportGridService] = useViewportGrid(); const [measurementSelected, setMeasurementSelected] = useState(0); const [measurementCount, setMeasurementCount] = useState(1); @@ -160,13 +150,13 @@ function OHIFCornerstoneSRMeasurementViewport(props: withAppTypes) { setActiveImageDisplaySetData(referencedDisplaySet); setReferencedDisplaySetMetadata(referencedDisplaySetMetadata); - const { presentationIds } = viewportOptions - const measurement = srDisplaySet.measurements[newMeasurementSelected] - setPositionPresentation(presentationIds.positionPresentationId, { + const { presentationIds } = viewportOptions; + const measurement = srDisplaySet.measurements[newMeasurementSelected]; + setPositionPresentation(presentationIds.positionPresentationId, { viewReference: { - referencedImageId: measurement.imageId - } - }) + referencedImageId: measurement.imageId, + }, + }); }); }, [dataSource, srDisplaySet, activeImageDisplaySetData, viewportId] @@ -188,8 +178,6 @@ function OHIFCornerstoneSRMeasurementViewport(props: withAppTypes) { return null; } - - return ( ; const scalarData = voxelManager.getScalarData(); - scalarData.set(volumeScalarData.slice(i * scalarData.length, (i + 1) * scalarData.length)); + const sliceData = volumeScalarData.slice(i * scalarData.length, (i + 1) * scalarData.length); + scalarData.set(sliceData); voxelManager.setScalarData(scalarData); + + // Check if this slice has any non-zero voxels and we haven't found one yet + if (!firstSegmentedSliceImageId && sliceData.some(value => value !== 0)) { + firstSegmentedSliceImageId = derivedSegmentationImages[i].referencedImageId; + } } + // assign the first non zero voxel image id to the segDisplaySet + segDisplaySet.firstSegmentedSliceImageId = firstSegmentedSliceImageId; + this._broadcastEvent(EVENTS.SEGMENTATION_LOADING_COMPLETE, { segmentationId, segDisplaySet, @@ -543,7 +553,19 @@ class SegmentationService extends PubSubService { } const rtDisplaySetUID = rtDisplaySet.displaySetInstanceUID; + const referencedDisplaySet = this.servicesManager.services.displaySetService.getDisplaySetByUID( + rtDisplaySet.referencedDisplaySetInstanceUID + ); + const referencedImageIdsWithGeometry = Array.from(structureSet.ReferencedSOPInstanceUIDsSet); + + const referencedImageIds = referencedDisplaySet.instances.map(image => image.imageId); + // find the first image id that contains a referenced SOP instance UID + const firstSegmentedSliceImageId = referencedImageIds.find(imageId => + referencedImageIdsWithGeometry.some(referencedId => imageId.includes(referencedId)) + ); + + rtDisplaySet.firstSegmentedSliceImageId = firstSegmentedSliceImageId; // Map ROI contours to RT Struct Data const allRTStructData = mapROIContoursToRTStructData(structureSet, rtDisplaySetUID); diff --git a/extensions/cornerstone/src/services/ViewportService/CornerstoneViewportService.ts b/extensions/cornerstone/src/services/ViewportService/CornerstoneViewportService.ts index 9c9bc5909..4cca464cd 100644 --- a/extensions/cornerstone/src/services/ViewportService/CornerstoneViewportService.ts +++ b/extensions/cornerstone/src/services/ViewportService/CornerstoneViewportService.ts @@ -605,10 +605,6 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi let initialImageIndexToUse = presentations?.positionPresentation?.initialImageIndex ?? initialImageIndex; - if (initialImageIndexToUse === undefined || initialImageIndexToUse === null) { - initialImageIndexToUse = this._getInitialImageIndexForViewport(viewportInfo, imageIds) || 0; - } - const { rotation, flipHorizontal, displayArea } = viewportInfo.getViewportOptions(); const properties = { ...presentations.lutPresentation?.properties }; @@ -637,12 +633,26 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi }); let imageIdsToSet = imageIds; - const res = this._processExtraDisplaySetsForViewport(viewport); - imageIdsToSet = res?.imageIds ?? imageIdsToSet; + const overlayProcessingResult = this._processExtraDisplaySetsForViewport(viewport); + imageIdsToSet = overlayProcessingResult?.imageIds ?? imageIdsToSet; + + const referencedImageId = presentations?.positionPresentation?.viewReference?.referencedImageId; + if (referencedImageId) { + initialImageIndexToUse = imageIdsToSet.indexOf(referencedImageId); + } + + if (initialImageIndexToUse === undefined || initialImageIndexToUse === null) { + initialImageIndexToUse = this._getInitialImageIndexForViewport(viewportInfo, imageIds) || 0; + } return viewport.setStack(imageIdsToSet, initialImageIndexToUse).then(() => { viewport.setProperties({ ...properties }); this.setPresentations(viewport.id, presentations, viewportInfo); + + if (overlayProcessingResult?.addOverlayFn) { + overlayProcessingResult.addOverlayFn(); + } + if (displayArea) { viewport.setDisplayArea(displayArea); } @@ -827,10 +837,14 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi }); // For SEG and RT viewports - this._processExtraDisplaySetsForViewport(viewport); + const { addOverlayFn } = this._processExtraDisplaySetsForViewport(viewport) || {}; await viewport.setVolumes(volumeInputArray); + if (addOverlayFn) { + addOverlayFn(); + } + volumesProperties.forEach(({ properties, volumeId }) => { viewport.setProperties(properties, volumeId); }); @@ -880,8 +894,12 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi segOrRTSOverlayDisplaySet.referencedDisplaySetInstanceUID ); const imageIds = referenceDisplaySet.images.map(image => image.imageId); - this.addOverlayRepresentationForDisplaySet(segOrRTSOverlayDisplaySet, viewport); - return { imageIds }; + + return { + imageIds, + addOverlayFn: () => + this.addOverlayRepresentationForDisplaySet(segOrRTSOverlayDisplaySet, viewport), + }; } private addOverlayRepresentationForDisplaySet( diff --git a/extensions/default/src/getHangingProtocolModule.js b/extensions/default/src/getHangingProtocolModule.js index ec0da3579..a65891ea5 100644 --- a/extensions/default/src/getHangingProtocolModule.js +++ b/extensions/default/src/getHangingProtocolModule.js @@ -63,7 +63,7 @@ const defaultProtocol = { // It has no affect if nothing is specified in the URL. { attribute: 'isDisplaySetFromUrl', - weight: 10, + weight: 20, constraint: { equals: true, }, diff --git a/extensions/default/src/hangingprotocols/hpCompare.ts b/extensions/default/src/hangingprotocols/hpCompare.ts index 87a4f5e02..14cb51d93 100644 --- a/extensions/default/src/hangingprotocols/hpCompare.ts +++ b/extensions/default/src/hangingprotocols/hpCompare.ts @@ -24,7 +24,7 @@ const defaultDisplaySetSelector = { // It has no affect if nothing is specified in the URL. { attribute: 'isDisplaySetFromUrl', - weight: 10, + weight: 20, constraint: { equals: true, }, @@ -56,7 +56,7 @@ const priorDisplaySetSelector = { // It has no affect if nothing is specified in the URL. { attribute: 'isDisplaySetFromUrl', - weight: 10, + weight: 20, constraint: { equals: true, }, diff --git a/extensions/default/src/hangingprotocols/hpMNGrid.ts b/extensions/default/src/hangingprotocols/hpMNGrid.ts index 1f07242c8..0c31815d2 100644 --- a/extensions/default/src/hangingprotocols/hpMNGrid.ts +++ b/extensions/default/src/hangingprotocols/hpMNGrid.ts @@ -50,7 +50,7 @@ const hpMN: Types.HangingProtocol.Protocol = { // It has no affect if nothing is specified in the URL. { attribute: 'isDisplaySetFromUrl', - weight: 10, + weight: 20, constraint: { equals: true, }, diff --git a/extensions/default/src/hangingprotocols/hpScale.ts b/extensions/default/src/hangingprotocols/hpScale.ts index 651413c24..e76f5d591 100644 --- a/extensions/default/src/hangingprotocols/hpScale.ts +++ b/extensions/default/src/hangingprotocols/hpScale.ts @@ -43,7 +43,7 @@ const hpScale: Types.HangingProtocol.Protocol = { // It has no affect if nothing is specified in the URL. { attribute: 'isDisplaySetFromUrl', - weight: 10, + weight: 20, constraint: { equals: true, }, diff --git a/extensions/test-extension/src/hpTestSwitch.ts b/extensions/test-extension/src/hpTestSwitch.ts index 8b3fda5aa..4e497a61e 100644 --- a/extensions/test-extension/src/hpTestSwitch.ts +++ b/extensions/test-extension/src/hpTestSwitch.ts @@ -188,7 +188,7 @@ const hpTestSwitch: Types.HangingProtocol.Protocol = { // It has no affect if nothing is specified in the URL. { attribute: 'isDisplaySetFromUrl', - weight: 10, + weight: 20, constraint: { equals: true, }, diff --git a/platform/app/public/config/local_orthanc.js b/platform/app/public/config/local_orthanc.js index b5c287f5f..a3bdc8ace 100644 --- a/platform/app/public/config/local_orthanc.js +++ b/platform/app/public/config/local_orthanc.js @@ -23,6 +23,7 @@ window.config = { wadoRoot: 'http://localhost/dicom-web', qidoSupportsIncludeField: true, supportsReject: true, + dicomUploadEnabled: true, imageRendering: 'wadors', thumbnailRendering: 'wadors', enableStudyLazyLoad: true, diff --git a/yarn.lock b/yarn.lock index a074e8391..c66e69ce3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2580,10 +2580,10 @@ resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== -"@cornerstonejs/adapters@^2.7.3": - version "2.7.3" - resolved "https://registry.yarnpkg.com/@cornerstonejs/adapters/-/adapters-2.7.3.tgz#96d2ab568bfc987a6c7bb44f849ad2f94be9014a" - integrity sha512-hEJusn3DynPrgyaAidOoYboFJ/t5dd1TDaIiIr2FQQbfkIhun6EE5UkLOcdP8dqiKujpsHm9LcdCFh/b3/7K8g== +"@cornerstonejs/adapters@^2.11.2": + version "2.11.5" + resolved "https://registry.yarnpkg.com/@cornerstonejs/adapters/-/adapters-2.11.5.tgz#21b799917e09a002465e84412ab123a778d3d2a0" + integrity sha512-nLtbCXqyjtQH59KthjnlB3I8MgNo9bZt/nYPWdm4K3FTMXRafJ8sp4oc1VWpeHJlAAgmnyq0PEKaWY2K0Y+S3w== dependencies: "@babel/runtime-corejs2" "^7.17.8" buffer "^6.0.3" @@ -2616,19 +2616,19 @@ resolved "https://registry.yarnpkg.com/@cornerstonejs/codec-openjph/-/codec-openjph-2.4.5.tgz#8690b61a86fa53ef38a70eee9d665a79229517c0" integrity sha512-MZCUy8VG0VG5Nl1l58+g+kH3LujAzLYTfJqkwpWI2gjSrGXnP6lgwyy4GmPRZWVoS40/B1LDNALK905cNWm+sg== -"@cornerstonejs/core@^2.7.3": - version "2.7.3" - resolved "https://registry.yarnpkg.com/@cornerstonejs/core/-/core-2.7.3.tgz#0e580e3052b84530f0da4fb4b94e23f580415f47" - integrity sha512-q3Sc1eiRlC6kAzgqkJ/cGFGpJe62YwinS2nbZceqDKoAno3C4W81h5jrolENKH4HEOS6qvuz3sPP/sh6ryg/zA== +"@cornerstonejs/core@^2.11.2": + version "2.11.5" + resolved "https://registry.yarnpkg.com/@cornerstonejs/core/-/core-2.11.5.tgz#2c45ca7b3f8032752f3d9ed787fa14e7a77cb739" + integrity sha512-RB3zkk88sVdVwtWGbG2V9rTXhZHNwxGOiQrkftRZqMF17bFTLqPEHkpf/PZveNUcZmjaqn0oPlKXD8QmedJonA== dependencies: "@kitware/vtk.js" "32.1.1" comlink "^4.4.1" gl-matrix "^3.4.3" -"@cornerstonejs/dicom-image-loader@^2.7.3": - version "2.7.3" - resolved "https://registry.yarnpkg.com/@cornerstonejs/dicom-image-loader/-/dicom-image-loader-2.7.3.tgz#04466643bd3802933378460d60a731d9cc3a34e3" - integrity sha512-P5wZovDo5onMIMILwNRrlv75GYnDFIFVQfnvepJKTfNTeQbHhTaNRfx8MHOHNYCa8JBtrR6JSeD2FkMoZE/vsg== +"@cornerstonejs/dicom-image-loader@^2.11.2": + version "2.11.5" + resolved "https://registry.yarnpkg.com/@cornerstonejs/dicom-image-loader/-/dicom-image-loader-2.11.5.tgz#b3acf689b23c9db61f5b0c8fba26e7ec2144deb4" + integrity sha512-xdYBHMAMlilziXYUYvMh9nrfTl0O26kvFowWRMeIjP2SwTtsYQqCri9CsRxf6giJRcsw3gVn0PhUdZpfzX6vSQ== dependencies: "@cornerstonejs/codec-charls" "^1.2.3" "@cornerstonejs/codec-libjpeg-turbo-8bit" "^1.2.2" @@ -2639,10 +2639,10 @@ pako "^2.0.4" uuid "^9.0.0" -"@cornerstonejs/tools@^2.7.3": - version "2.7.3" - resolved "https://registry.yarnpkg.com/@cornerstonejs/tools/-/tools-2.7.3.tgz#9e2cbbb4d5d6e3b6b6f42f631d51a433a337b201" - integrity sha512-03WRQ5AX5RQmaqc7uSkgv9npruCBbRExjp4FOlOHU7Tq16q7CJlqIPF1wWEqecoxn7T1IXL3bokXOTPvh8zSFQ== +"@cornerstonejs/tools@^2.11.2": + version "2.11.5" + resolved "https://registry.yarnpkg.com/@cornerstonejs/tools/-/tools-2.11.5.tgz#f8a50fd636172e5895781a429d85b22a49a1021c" + integrity sha512-n9ScPe0d73dXR5RgblhRPkrQ+hmzzx6/3ykH2jaf/kr52tzfNO3qxyZURPDAusC/sOJ2Rk2yVqQBv0dMhKYi0Q== dependencies: "@types/offscreencanvas" "2019.7.3" comlink "^4.4.1"