@cornerstonejs/core 2.0.0-beta.1 → 2.0.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/RenderingEngine/BaseVolumeViewport.d.ts +4 -1
- package/dist/cjs/RenderingEngine/BaseVolumeViewport.js +28 -2
- package/dist/cjs/RenderingEngine/BaseVolumeViewport.js.map +1 -1
- package/dist/cjs/RenderingEngine/RenderingEngine.js.map +1 -1
- package/dist/cjs/RenderingEngine/StackViewport.d.ts +1 -0
- package/dist/cjs/RenderingEngine/StackViewport.js +17 -8
- package/dist/cjs/RenderingEngine/StackViewport.js.map +1 -1
- package/dist/cjs/RenderingEngine/VolumeViewport.d.ts +2 -0
- package/dist/cjs/RenderingEngine/VolumeViewport.js +30 -0
- package/dist/cjs/RenderingEngine/VolumeViewport.js.map +1 -1
- package/dist/cjs/RenderingEngine/VolumeViewport3D.d.ts +1 -0
- package/dist/cjs/RenderingEngine/VolumeViewport3D.js +3 -0
- package/dist/cjs/RenderingEngine/VolumeViewport3D.js.map +1 -1
- package/dist/cjs/RenderingEngine/helpers/cpuFallback/rendering/getVOILut.js +3 -1
- package/dist/cjs/RenderingEngine/helpers/cpuFallback/rendering/getVOILut.js.map +1 -1
- package/dist/cjs/RenderingEngine/helpers/cpuFallback/rendering/renderColorImage.js +3 -2
- package/dist/cjs/RenderingEngine/helpers/cpuFallback/rendering/renderColorImage.js.map +1 -1
- package/dist/cjs/RenderingEngine/helpers/setVolumesForViewports.js.map +1 -1
- package/dist/cjs/Settings.js +4 -2
- package/dist/cjs/Settings.js.map +1 -1
- package/dist/cjs/cache/cache.d.ts +3 -1
- package/dist/cjs/cache/cache.js +12 -7
- package/dist/cjs/cache/cache.js.map +1 -1
- package/dist/cjs/cache/classes/ImageVolume.js +2 -3
- package/dist/cjs/cache/classes/ImageVolume.js.map +1 -1
- package/dist/cjs/init.d.ts +1 -1
- package/dist/cjs/init.js +1 -1
- package/dist/cjs/init.js.map +1 -1
- package/dist/cjs/loaders/volumeLoader.d.ts +1 -1
- package/dist/cjs/loaders/volumeLoader.js.map +1 -1
- package/dist/cjs/requestPool/requestPoolManager.js +1 -1
- package/dist/cjs/requestPool/requestPoolManager.js.map +1 -1
- package/dist/cjs/types/AffineMatrix.d.ts +27 -0
- package/dist/cjs/types/AffineMatrix.js +3 -0
- package/dist/cjs/types/AffineMatrix.js.map +1 -0
- package/dist/cjs/types/IImage.d.ts +3 -0
- package/dist/cjs/types/IVolumeViewport.d.ts +2 -0
- package/dist/cjs/types/Mat3.d.ts +1 -11
- package/dist/cjs/types/ViewportProperties.d.ts +2 -1
- package/dist/cjs/types/index.d.ts +2 -1
- package/dist/cjs/utilities/calculateViewportsSpatialRegistration.js +9 -14
- package/dist/cjs/utilities/calculateViewportsSpatialRegistration.js.map +1 -1
- package/dist/cjs/utilities/getClosestStackImageIndexForPoint.js +12 -6
- package/dist/cjs/utilities/getClosestStackImageIndexForPoint.js.map +1 -1
- package/dist/cjs/utilities/getRuntimeId.js +2 -1
- package/dist/cjs/utilities/getRuntimeId.js.map +1 -1
- package/dist/cjs/utilities/windowLevel.js +4 -4
- package/dist/cjs/utilities/windowLevel.js.map +1 -1
- package/dist/esm/RenderingEngine/BaseVolumeViewport.d.ts +4 -1
- package/dist/esm/RenderingEngine/BaseVolumeViewport.js +28 -2
- package/dist/esm/RenderingEngine/BaseVolumeViewport.js.map +1 -1
- package/dist/esm/RenderingEngine/RenderingEngine.js.map +1 -1
- package/dist/esm/RenderingEngine/StackViewport.d.ts +1 -0
- package/dist/esm/RenderingEngine/StackViewport.js +17 -8
- package/dist/esm/RenderingEngine/StackViewport.js.map +1 -1
- package/dist/esm/RenderingEngine/VolumeViewport.d.ts +2 -0
- package/dist/esm/RenderingEngine/VolumeViewport.js +32 -2
- package/dist/esm/RenderingEngine/VolumeViewport.js.map +1 -1
- package/dist/esm/RenderingEngine/VolumeViewport3D.d.ts +1 -0
- package/dist/esm/RenderingEngine/VolumeViewport3D.js +3 -0
- package/dist/esm/RenderingEngine/VolumeViewport3D.js.map +1 -1
- package/dist/esm/RenderingEngine/helpers/cpuFallback/rendering/getVOILut.js +3 -1
- package/dist/esm/RenderingEngine/helpers/cpuFallback/rendering/getVOILut.js.map +1 -1
- package/dist/esm/RenderingEngine/helpers/cpuFallback/rendering/renderColorImage.js +3 -2
- package/dist/esm/RenderingEngine/helpers/cpuFallback/rendering/renderColorImage.js.map +1 -1
- package/dist/esm/RenderingEngine/helpers/setVolumesForViewports.js.map +1 -1
- package/dist/esm/Settings.js +4 -2
- package/dist/esm/Settings.js.map +1 -1
- package/dist/esm/cache/cache.d.ts +3 -1
- package/dist/esm/cache/cache.js +12 -7
- package/dist/esm/cache/cache.js.map +1 -1
- package/dist/esm/cache/classes/ImageVolume.js +2 -3
- package/dist/esm/cache/classes/ImageVolume.js.map +1 -1
- package/dist/esm/init.d.ts +1 -1
- package/dist/esm/init.js +1 -1
- package/dist/esm/init.js.map +1 -1
- package/dist/esm/loaders/volumeLoader.d.ts +1 -1
- package/dist/esm/loaders/volumeLoader.js.map +1 -1
- package/dist/esm/requestPool/requestPoolManager.js +1 -1
- package/dist/esm/requestPool/requestPoolManager.js.map +1 -1
- package/dist/esm/types/AffineMatrix.d.ts +27 -0
- package/dist/esm/types/AffineMatrix.js +2 -0
- package/dist/esm/types/AffineMatrix.js.map +1 -0
- package/dist/esm/types/IImage.d.ts +3 -0
- package/dist/esm/types/IVolumeViewport.d.ts +2 -0
- package/dist/esm/types/Mat3.d.ts +1 -11
- package/dist/esm/types/ViewportProperties.d.ts +2 -1
- package/dist/esm/types/index.d.ts +2 -1
- package/dist/esm/utilities/calculateViewportsSpatialRegistration.js +9 -14
- package/dist/esm/utilities/calculateViewportsSpatialRegistration.js.map +1 -1
- package/dist/esm/utilities/getClosestStackImageIndexForPoint.js +12 -6
- package/dist/esm/utilities/getClosestStackImageIndexForPoint.js.map +1 -1
- package/dist/esm/utilities/getRuntimeId.js +2 -1
- package/dist/esm/utilities/getRuntimeId.js.map +1 -1
- package/dist/esm/utilities/windowLevel.js +4 -4
- package/dist/esm/utilities/windowLevel.js.map +1 -1
- package/dist/umd/index.js +1 -1
- package/dist/umd/index.js.map +1 -1
- package/package.json +2 -2
- package/src/RenderingEngine/BaseVolumeViewport.ts +55 -1
- package/src/RenderingEngine/RenderingEngine.ts +1 -0
- package/src/RenderingEngine/StackViewport.ts +25 -9
- package/src/RenderingEngine/Viewport.ts +1 -1
- package/src/RenderingEngine/VolumeViewport.ts +53 -2
- package/src/RenderingEngine/VolumeViewport3D.ts +4 -0
- package/src/RenderingEngine/helpers/cpuFallback/rendering/getVOILut.ts +9 -1
- package/src/RenderingEngine/helpers/cpuFallback/rendering/renderColorImage.ts +5 -3
- package/src/RenderingEngine/helpers/setVolumesForViewports.ts +3 -1
- package/src/Settings.ts +6 -2
- package/src/cache/cache.ts +33 -18
- package/src/cache/classes/ImageVolume.ts +3 -3
- package/src/init.ts +1 -1
- package/src/loaders/volumeLoader.ts +2 -2
- package/src/requestPool/requestPoolManager.ts +1 -1
- package/src/types/AffineMatrix.ts +8 -0
- package/src/types/IImage.ts +4 -0
- package/src/types/IVolumeViewport.ts +8 -0
- package/src/types/Mat3.ts +3 -11
- package/src/types/ViewportProperties.ts +3 -1
- package/src/types/index.ts +2 -0
- package/src/utilities/calculateViewportsSpatialRegistration.ts +21 -28
- package/src/utilities/getClosestStackImageIndexForPoint.ts +18 -6
- package/src/utilities/getRuntimeId.ts +3 -1
- package/src/utilities/windowLevel.ts +13 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cornerstonejs/core",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.3",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "dist/umd/index.js",
|
|
6
6
|
"types": "dist/esm/index.d.ts",
|
|
@@ -46,5 +46,5 @@
|
|
|
46
46
|
"type": "individual",
|
|
47
47
|
"url": "https://ohif.org/donate"
|
|
48
48
|
},
|
|
49
|
-
"gitHead": "
|
|
49
|
+
"gitHead": "d78cf780d4383a61ea0a9762bafa4104666757a4"
|
|
50
50
|
}
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
import {
|
|
13
13
|
BlendModes,
|
|
14
14
|
Events,
|
|
15
|
+
InterpolationType,
|
|
15
16
|
OrientationAxis,
|
|
16
17
|
ViewportStatus,
|
|
17
18
|
VOILUTFunctionType,
|
|
@@ -367,6 +368,23 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
|
|
|
367
368
|
return newRGBTransferFunction;
|
|
368
369
|
}
|
|
369
370
|
|
|
371
|
+
private setInterpolationType(
|
|
372
|
+
interpolationType: InterpolationType,
|
|
373
|
+
volumeId?: string
|
|
374
|
+
) {
|
|
375
|
+
const applicableVolumeActorInfo = this._getApplicableVolumeActor(volumeId);
|
|
376
|
+
|
|
377
|
+
if (!applicableVolumeActorInfo) {
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
const { volumeActor } = applicableVolumeActorInfo;
|
|
382
|
+
const volumeProperty = volumeActor.getProperty();
|
|
383
|
+
|
|
384
|
+
// @ts-ignore
|
|
385
|
+
volumeProperty.setInterpolationType(interpolationType);
|
|
386
|
+
}
|
|
387
|
+
|
|
370
388
|
/**
|
|
371
389
|
* Sets the properties for the volume viewport on the volume
|
|
372
390
|
* (if fusion, it sets it for the first volume in the fusion)
|
|
@@ -449,6 +467,7 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
|
|
|
449
467
|
invert,
|
|
450
468
|
colormap,
|
|
451
469
|
preset,
|
|
470
|
+
interpolationType,
|
|
452
471
|
}: VolumeViewportProperties = {},
|
|
453
472
|
volumeId?: string,
|
|
454
473
|
suppressEvents = false
|
|
@@ -467,6 +486,10 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
|
|
|
467
486
|
this.setVOI(voiRange, volumeId, suppressEvents);
|
|
468
487
|
}
|
|
469
488
|
|
|
489
|
+
if (typeof interpolationType !== 'undefined') {
|
|
490
|
+
this.setInterpolationType(interpolationType);
|
|
491
|
+
}
|
|
492
|
+
|
|
470
493
|
if (VOILUTFunction !== undefined) {
|
|
471
494
|
this.setVOILUTFunction(VOILUTFunction, volumeId, suppressEvents);
|
|
472
495
|
}
|
|
@@ -519,7 +542,9 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
|
|
|
519
542
|
const volumeActor = actorEntry.actor as vtkVolume;
|
|
520
543
|
const volumeId = actorEntry.uid;
|
|
521
544
|
const volume = cache.getVolume(volumeId);
|
|
522
|
-
if (!volume)
|
|
545
|
+
if (!volume) {
|
|
546
|
+
return null;
|
|
547
|
+
}
|
|
523
548
|
const cfun = volumeActor.getProperty().getRGBTransferFunction(0);
|
|
524
549
|
const [lower, upper] =
|
|
525
550
|
this.VOILUTFunction === 'SIGMOID'
|
|
@@ -847,6 +872,8 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
|
|
|
847
872
|
*
|
|
848
873
|
*/
|
|
849
874
|
private _setVolumeActors(volumeActorEntries: Array<ActorEntry>): void {
|
|
875
|
+
// New volume actors implies resetting the inverted flag (i.e. like starting from scratch).
|
|
876
|
+
this.inverted = false;
|
|
850
877
|
this.setActors(volumeActorEntries);
|
|
851
878
|
}
|
|
852
879
|
|
|
@@ -1078,6 +1105,31 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
|
|
|
1078
1105
|
return volume.getScalarData()[voxelIndex];
|
|
1079
1106
|
}
|
|
1080
1107
|
|
|
1108
|
+
/**
|
|
1109
|
+
* Returns the list of image Ids for the current viewport
|
|
1110
|
+
*
|
|
1111
|
+
* @param volumeId - volumeId
|
|
1112
|
+
* @returns list of strings for image Ids
|
|
1113
|
+
*/
|
|
1114
|
+
public getImageIds = (volumeId?: string): Array<string> => {
|
|
1115
|
+
const applicableVolumeActorInfo = this._getApplicableVolumeActor(volumeId);
|
|
1116
|
+
|
|
1117
|
+
if (!applicableVolumeActorInfo) {
|
|
1118
|
+
throw new Error(`No actor found for the given volumeId: ${volumeId}`);
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
const volumeIdToUse = applicableVolumeActorInfo.volumeId;
|
|
1122
|
+
|
|
1123
|
+
const imageVolume = cache.getVolume(volumeIdToUse);
|
|
1124
|
+
if (!imageVolume) {
|
|
1125
|
+
throw new Error(
|
|
1126
|
+
`imageVolume with id: ${volumeIdToUse} does not exist in cache`
|
|
1127
|
+
);
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
return imageVolume.imageIds;
|
|
1131
|
+
};
|
|
1132
|
+
|
|
1081
1133
|
abstract getCurrentImageIdIndex(): number;
|
|
1082
1134
|
|
|
1083
1135
|
abstract getCurrentImageId(): string;
|
|
@@ -1092,6 +1144,8 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
|
|
|
1092
1144
|
slabThickness: number,
|
|
1093
1145
|
filterActorUIDs?: Array<string>
|
|
1094
1146
|
): void;
|
|
1147
|
+
|
|
1148
|
+
abstract resetProperties(volumeId?: string): void;
|
|
1095
1149
|
}
|
|
1096
1150
|
|
|
1097
1151
|
export default BaseVolumeViewport;
|
|
@@ -54,6 +54,7 @@ const VIEWPORT_MIN_SIZE = 2;
|
|
|
54
54
|
* trigger a render on a specific viewport(s). Each viewport also has a `.render` method which can be used to trigger a render on that
|
|
55
55
|
* viewport.
|
|
56
56
|
*
|
|
57
|
+
*
|
|
57
58
|
* Rendering engine uses `detect-gpu` external library to detect if GPU is available and
|
|
58
59
|
* it has minimum requirement to be able to render a volume with vtk.js. If GPU is not available
|
|
59
60
|
* RenderingEngine will throw an error if you try to render a volume; however, for StackViewports
|
|
@@ -130,6 +130,8 @@ class StackViewport extends Viewport implements IStackViewport {
|
|
|
130
130
|
private VOILUTFunction: VOILUTFunctionType;
|
|
131
131
|
//
|
|
132
132
|
private invert = false;
|
|
133
|
+
// The initial invert of the image loaded as opposed to the invert status of the viewport itself (see above).
|
|
134
|
+
private initialInvert = false;
|
|
133
135
|
private interpolationType: InterpolationType;
|
|
134
136
|
|
|
135
137
|
// Helpers
|
|
@@ -606,7 +608,9 @@ class StackViewport extends Viewport implements IStackViewport {
|
|
|
606
608
|
this.hasPixelSpacing = scale > 0 || imagePlaneModule.rowPixelSpacing > 0;
|
|
607
609
|
imagePlaneModule.calibration = calibration;
|
|
608
610
|
|
|
609
|
-
if (!isUpdated)
|
|
611
|
+
if (!isUpdated) {
|
|
612
|
+
return imagePlaneModule;
|
|
613
|
+
}
|
|
610
614
|
|
|
611
615
|
this.calibration = calibration;
|
|
612
616
|
this._publishCalibratedEvent = true;
|
|
@@ -728,7 +732,7 @@ class StackViewport extends Viewport implements IStackViewport {
|
|
|
728
732
|
this.setRotation(0);
|
|
729
733
|
}
|
|
730
734
|
this.setInterpolationType(InterpolationType.LINEAR);
|
|
731
|
-
this.setInvertColor(
|
|
735
|
+
this.setInvertColor(this.initialInvert);
|
|
732
736
|
}
|
|
733
737
|
|
|
734
738
|
private _setPropertiesFromCache(): void {
|
|
@@ -1013,7 +1017,7 @@ class StackViewport extends Viewport implements IStackViewport {
|
|
|
1013
1017
|
? vec3.negate(vec3.create(), this.initialViewUp)
|
|
1014
1018
|
: this.initialViewUp;
|
|
1015
1019
|
|
|
1016
|
-
this.
|
|
1020
|
+
this.setCameraNoEvent({
|
|
1017
1021
|
viewUp: initialViewUp as Point3,
|
|
1018
1022
|
});
|
|
1019
1023
|
|
|
@@ -1755,10 +1759,17 @@ class StackViewport extends Viewport implements IStackViewport {
|
|
|
1755
1759
|
return;
|
|
1756
1760
|
}
|
|
1757
1761
|
|
|
1758
|
-
//If Photometric Interpretation is not the same for the next image we are trying to load
|
|
1762
|
+
// If Photometric Interpretation is not the same for the next image we are trying to load
|
|
1763
|
+
// invalidate the stack to recreate the VTK imageData
|
|
1764
|
+
const csImgFrame = this.csImage?.imageFrame;
|
|
1765
|
+
const imgFrame = image?.imageFrame;
|
|
1766
|
+
|
|
1767
|
+
// if a volume is decached into images then the imageFrame will be undefined
|
|
1759
1768
|
if (
|
|
1760
|
-
|
|
1761
|
-
|
|
1769
|
+
csImgFrame?.photometricInterpretation !==
|
|
1770
|
+
imgFrame?.photometricInterpretation ||
|
|
1771
|
+
this.csImage?.photometricInterpretation !==
|
|
1772
|
+
image?.photometricInterpretation
|
|
1762
1773
|
) {
|
|
1763
1774
|
this.stackInvalidated = true;
|
|
1764
1775
|
}
|
|
@@ -2057,8 +2068,10 @@ class StackViewport extends Viewport implements IStackViewport {
|
|
|
2057
2068
|
forceRecreateLUTFunction: !!monochrome1,
|
|
2058
2069
|
});
|
|
2059
2070
|
|
|
2071
|
+
this.initialInvert = !!monochrome1;
|
|
2072
|
+
|
|
2060
2073
|
// should carry over the invert color from the previous image if has been applied
|
|
2061
|
-
this.setInvertColor(this.invert ||
|
|
2074
|
+
this.setInvertColor(this.invert || this.initialInvert);
|
|
2062
2075
|
|
|
2063
2076
|
// Saving position of camera on render, to cache the panning
|
|
2064
2077
|
this.cameraFocalPointOnRender = this.getCamera().focalPoint;
|
|
@@ -2142,6 +2155,7 @@ class StackViewport extends Viewport implements IStackViewport {
|
|
|
2142
2155
|
// Update the state of the viewport to the new imageIdIndex;
|
|
2143
2156
|
this.currentImageIdIndex = imageIdIndex;
|
|
2144
2157
|
this.hasPixelSpacing = true;
|
|
2158
|
+
this.viewportStatus = ViewportStatus.PRE_RENDER;
|
|
2145
2159
|
|
|
2146
2160
|
// Todo: trigger an event to allow applications to hook into START of loading state
|
|
2147
2161
|
// Currently we use loadHandlerManagers for this
|
|
@@ -2225,7 +2239,7 @@ class StackViewport extends Viewport implements IStackViewport {
|
|
|
2225
2239
|
|
|
2226
2240
|
const targetImageId = imageIds[newTargetImageIdIndex];
|
|
2227
2241
|
|
|
2228
|
-
const imageAlreadyLoaded = cache.
|
|
2242
|
+
const imageAlreadyLoaded = cache.isLoaded(targetImageId);
|
|
2229
2243
|
|
|
2230
2244
|
// If image is already cached we want to scroll right away; however, if it is
|
|
2231
2245
|
// not cached, we can debounce the scroll event to avoid firing multiple scroll
|
|
@@ -2564,7 +2578,9 @@ class StackViewport extends Viewport implements IStackViewport {
|
|
|
2564
2578
|
public hasImageURI = (imageURI: string): boolean => {
|
|
2565
2579
|
const imageIds = this.imageIds;
|
|
2566
2580
|
for (let i = 0; i < imageIds.length; i++) {
|
|
2567
|
-
if (imageIdToURI(imageIds[i]) === imageURI)
|
|
2581
|
+
if (imageIdToURI(imageIds[i]) === imageURI) {
|
|
2582
|
+
return true;
|
|
2583
|
+
}
|
|
2568
2584
|
}
|
|
2569
2585
|
|
|
2570
2586
|
return false;
|
|
@@ -126,7 +126,7 @@ class Viewport implements IViewport {
|
|
|
126
126
|
|
|
127
127
|
/**
|
|
128
128
|
* Indicate that the image has been rendered.
|
|
129
|
-
* This will set
|
|
129
|
+
* This will set the viewportStatus to RENDERED if there is image data
|
|
130
130
|
* available to actually be rendered - otherwise, the rendering simply showed
|
|
131
131
|
* the background image.
|
|
132
132
|
*/
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import vtkPlane from '@kitware/vtk.js/Common/DataModel/Plane';
|
|
2
|
+
import vtkVolume from '@kitware/vtk.js/Rendering/Core/Volume';
|
|
3
|
+
|
|
2
4
|
import { vec3 } from 'gl-matrix';
|
|
3
5
|
|
|
4
6
|
import cache from '../cache';
|
|
5
7
|
import { MPR_CAMERA_VALUES, RENDERING_DEFAULTS } from '../constants';
|
|
6
|
-
import { BlendModes, OrientationAxis } from '../enums';
|
|
8
|
+
import { BlendModes, OrientationAxis, Events } from '../enums';
|
|
7
9
|
import type {
|
|
8
10
|
ActorEntry,
|
|
9
11
|
IImageVolume,
|
|
@@ -12,8 +14,9 @@ import type {
|
|
|
12
14
|
Point3,
|
|
13
15
|
} from '../types';
|
|
14
16
|
import type { ViewportInput } from '../types/IViewport';
|
|
15
|
-
import { actorIsA, getClosestImageId } from '../utilities';
|
|
17
|
+
import { actorIsA, getClosestImageId, triggerEvent } from '../utilities';
|
|
16
18
|
import BaseVolumeViewport from './BaseVolumeViewport';
|
|
19
|
+
import setDefaultVolumeVOI from './helpers/setDefaultVolumeVOI';
|
|
17
20
|
|
|
18
21
|
/**
|
|
19
22
|
* An object representing a VolumeViewport. VolumeViewports are used to render
|
|
@@ -350,6 +353,54 @@ class VolumeViewport extends BaseVolumeViewport {
|
|
|
350
353
|
};
|
|
351
354
|
|
|
352
355
|
getRotation = (): number => 0;
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Reset the viewport properties to the default values
|
|
359
|
+
*
|
|
360
|
+
|
|
361
|
+
* @param volumeId - Optional volume ID to specify which volume properties to reset.
|
|
362
|
+
* If not provided, it will reset the properties of the default actor.
|
|
363
|
+
*
|
|
364
|
+
* @returns void
|
|
365
|
+
*/
|
|
366
|
+
public resetProperties(volumeId?: string): void {
|
|
367
|
+
this._resetProperties(volumeId);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
private _resetProperties(volumeId?: string) {
|
|
371
|
+
// Get the actor based on the volumeId if provided, otherwise use the default actor.
|
|
372
|
+
const volumeActor = volumeId
|
|
373
|
+
? this.getActor(volumeId)
|
|
374
|
+
: this.getDefaultActor();
|
|
375
|
+
|
|
376
|
+
if (!volumeActor) {
|
|
377
|
+
throw new Error(`No actor found for the given volumeId: ${volumeId}`);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
const imageVolume = cache.getVolume(volumeActor.uid);
|
|
381
|
+
if (!imageVolume) {
|
|
382
|
+
throw new Error(
|
|
383
|
+
`imageVolume with id: ${volumeActor.uid} does not exist in cache`
|
|
384
|
+
);
|
|
385
|
+
}
|
|
386
|
+
setDefaultVolumeVOI(volumeActor.actor as vtkVolume, imageVolume, false);
|
|
387
|
+
|
|
388
|
+
const range = (volumeActor.actor as vtkVolume)
|
|
389
|
+
.getProperty()
|
|
390
|
+
.getRGBTransferFunction(0)
|
|
391
|
+
.getMappingRange();
|
|
392
|
+
|
|
393
|
+
const eventDetails = {
|
|
394
|
+
viewportId: volumeActor.uid,
|
|
395
|
+
range: {
|
|
396
|
+
lower: range[0],
|
|
397
|
+
upper: range[1],
|
|
398
|
+
},
|
|
399
|
+
volumeId: volumeActor.uid,
|
|
400
|
+
};
|
|
401
|
+
|
|
402
|
+
triggerEvent(this.element, Events.VOI_MODIFIED, eventDetails);
|
|
403
|
+
}
|
|
353
404
|
}
|
|
354
405
|
|
|
355
406
|
export default VolumeViewport;
|
|
@@ -15,6 +15,11 @@
|
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
|
+
* Generates the linear VOI LUT function.
|
|
19
|
+
* From the DICOM standard:
|
|
20
|
+
* https://dicom.nema.org/medical/dicom/current/output/html/part03.html#sect_C.11.2.1.2.1
|
|
21
|
+
* ((x - (c - 0.5)) / (w-1) + 0.5) * (ymax- ymin) + ymin
|
|
22
|
+
* clipped to the ymin...ymax range
|
|
18
23
|
*
|
|
19
24
|
* @param {Number} windowWidth Window Width
|
|
20
25
|
* @param {Number} windowCenter Window Center
|
|
@@ -23,7 +28,10 @@
|
|
|
23
28
|
*/
|
|
24
29
|
function generateLinearVOILUT(windowWidth: number, windowCenter: number) {
|
|
25
30
|
return function (modalityLutValue) {
|
|
26
|
-
|
|
31
|
+
const value =
|
|
32
|
+
((modalityLutValue - (windowCenter - 0.5)) / (windowWidth - 1) + 0.5) *
|
|
33
|
+
255.0;
|
|
34
|
+
return Math.min(Math.max(value, 0), 255);
|
|
27
35
|
};
|
|
28
36
|
}
|
|
29
37
|
|
|
@@ -72,10 +72,12 @@ function getRenderCanvas(
|
|
|
72
72
|
const renderCanvas = enabledElement.renderingTools.renderCanvas;
|
|
73
73
|
|
|
74
74
|
// The ww/wc is identity and not inverted - get a canvas with the image rendered into it for
|
|
75
|
-
// Fast drawing
|
|
75
|
+
// Fast drawing. Note that this is 256/128, and NOT 255/127, per the DICOM
|
|
76
|
+
// standard, but allow either.
|
|
77
|
+
const { windowWidth, windowCenter } = enabledElement.viewport.voi;
|
|
76
78
|
if (
|
|
77
|
-
|
|
78
|
-
|
|
79
|
+
(windowWidth === 256 || windowWidth === 255) &&
|
|
80
|
+
(windowCenter === 128 || windowCenter === 127) &&
|
|
79
81
|
enabledElement.viewport.invert === false &&
|
|
80
82
|
image.getCanvas &&
|
|
81
83
|
image.getCanvas()
|
|
@@ -34,7 +34,9 @@ async function setVolumesForViewports(
|
|
|
34
34
|
|
|
35
35
|
// if not instance of BaseVolumeViewport, throw
|
|
36
36
|
if (!(viewport instanceof BaseVolumeViewport)) {
|
|
37
|
-
throw new Error(
|
|
37
|
+
throw new Error(
|
|
38
|
+
'setVolumesForViewports only supports VolumeViewport and VolumeViewport3D'
|
|
39
|
+
);
|
|
38
40
|
}
|
|
39
41
|
});
|
|
40
42
|
|
package/src/Settings.ts
CHANGED
|
@@ -250,10 +250,14 @@ function get(dictionary: Record<string, unknown>, key: string): unknown {
|
|
|
250
250
|
*/
|
|
251
251
|
function isValidKey(key: string): boolean {
|
|
252
252
|
let last: number, current: number, previous: number;
|
|
253
|
-
if (typeof key !== 'string' || (last = key.length - 1) < 0)
|
|
253
|
+
if (typeof key !== 'string' || (last = key.length - 1) < 0) {
|
|
254
|
+
return false;
|
|
255
|
+
}
|
|
254
256
|
previous = -1;
|
|
255
257
|
while ((current = key.indexOf('.', previous + 1)) >= 0) {
|
|
256
|
-
if (current - previous < 2 || current === last)
|
|
258
|
+
if (current - previous < 2 || current === last) {
|
|
259
|
+
return false;
|
|
260
|
+
}
|
|
257
261
|
previous = current;
|
|
258
262
|
}
|
|
259
263
|
return true;
|
package/src/cache/cache.ts
CHANGED
|
@@ -15,34 +15,40 @@ import { triggerEvent, imageIdToURI } from '../utilities';
|
|
|
15
15
|
import eventTarget from '../eventTarget';
|
|
16
16
|
import Events from '../enums/Events';
|
|
17
17
|
|
|
18
|
-
const
|
|
18
|
+
const ONE_GB = 1073741824;
|
|
19
19
|
|
|
20
|
+
/**
|
|
21
|
+
* Stores images, volumes and geometry.
|
|
22
|
+
* There are two sizes - the max cache size, that controls the overal maximum
|
|
23
|
+
* size, and the instance size, which controls how big any single object can
|
|
24
|
+
* be. Defaults are 3 GB and 2 GB - 8 bytes (just enough to allow allocating it
|
|
25
|
+
* without crashing).
|
|
26
|
+
* The 3 gb is tuned to the chromium garbage collection cycle to allow image volumes
|
|
27
|
+
* to be used/discarded.
|
|
28
|
+
*/
|
|
20
29
|
class Cache implements ICache {
|
|
21
|
-
|
|
22
|
-
private readonly
|
|
30
|
+
// used to store image data (2d)
|
|
31
|
+
private readonly _imageCache = new Map<string, ICachedImage>(); // volatile space
|
|
32
|
+
// used to store volume data (3d)
|
|
33
|
+
private readonly _volumeCache = new Map<string, ICachedVolume>(); // non-volatile space
|
|
23
34
|
// Todo: contour for now, but will be used for surface, etc.
|
|
24
35
|
private readonly _geometryCache: Map<string, ICachedGeometry>;
|
|
25
|
-
|
|
26
|
-
private
|
|
27
|
-
private
|
|
36
|
+
|
|
37
|
+
private _imageCacheSize = 0;
|
|
38
|
+
private _volumeCacheSize = 0;
|
|
39
|
+
private _maxCacheSize = 3 * ONE_GB;
|
|
40
|
+
private _maxInstanceSize = 2 * ONE_GB - 8;
|
|
28
41
|
|
|
29
42
|
constructor() {
|
|
30
|
-
// used to store image data (2d)
|
|
31
|
-
this._imageCache = new Map();
|
|
32
|
-
// used to store volume data (3d)
|
|
33
|
-
this._volumeCache = new Map();
|
|
34
43
|
// used to store object data (contour, surface, etc.)
|
|
35
44
|
this._geometryCache = new Map();
|
|
36
|
-
this._imageCacheSize = 0;
|
|
37
|
-
this._volumeCacheSize = 0;
|
|
38
|
-
this._maxCacheSize = MAX_CACHE_SIZE_1GB; // Default 1GB
|
|
39
45
|
}
|
|
40
46
|
|
|
41
47
|
/**
|
|
42
48
|
* Set the maximum cache Size
|
|
43
49
|
*
|
|
44
|
-
* Maximum cache size should be set before adding the data
|
|
45
|
-
* will
|
|
50
|
+
* Maximum cache size should be set before adding the data. If set after,
|
|
51
|
+
* and it is smaller than the current size, will cause issues.
|
|
46
52
|
*
|
|
47
53
|
* @param newMaxCacheSize - new maximum cache size
|
|
48
54
|
*
|
|
@@ -59,7 +65,7 @@ class Cache implements ICache {
|
|
|
59
65
|
/**
|
|
60
66
|
* Checks if there is enough space in the cache for requested byte size
|
|
61
67
|
*
|
|
62
|
-
* It
|
|
68
|
+
* It returns false, if the sum of volatile (image) cache and unallocated cache
|
|
63
69
|
* is less than the requested byteLength
|
|
64
70
|
*
|
|
65
71
|
* @param byteLength - byte length of requested byte size
|
|
@@ -67,6 +73,9 @@ class Cache implements ICache {
|
|
|
67
73
|
* @returns - boolean indicating if there is enough space in the cache
|
|
68
74
|
*/
|
|
69
75
|
public isCacheable = (byteLength: number): boolean => {
|
|
76
|
+
if (byteLength > this._maxInstanceSize) {
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
70
79
|
const unallocatedSpace = this.getBytesAvailable();
|
|
71
80
|
const imageCacheSize = this._imageCacheSize;
|
|
72
81
|
const availableSpace = unallocatedSpace + imageCacheSize;
|
|
@@ -81,6 +90,13 @@ class Cache implements ICache {
|
|
|
81
90
|
*/
|
|
82
91
|
public getMaxCacheSize = (): number => this._maxCacheSize;
|
|
83
92
|
|
|
93
|
+
/**
|
|
94
|
+
* Returns maximum size of a single instance (volume or single image)
|
|
95
|
+
*
|
|
96
|
+
* @returns maximum instance size
|
|
97
|
+
*/
|
|
98
|
+
public getMaxInstanceSize = (): number => this._maxInstanceSize;
|
|
99
|
+
|
|
84
100
|
/**
|
|
85
101
|
* Returns current size of the cache
|
|
86
102
|
*
|
|
@@ -384,7 +400,6 @@ class Cache implements ICache {
|
|
|
384
400
|
cachedImage.image = image;
|
|
385
401
|
cachedImage.sizeInBytes = image.sizeInBytes;
|
|
386
402
|
this._incrementImageCacheSize(cachedImage.sizeInBytes);
|
|
387
|
-
|
|
388
403
|
const eventDetails: EventTypes.ImageCacheImageAddedEventDetail = {
|
|
389
404
|
image: cachedImage,
|
|
390
405
|
};
|
|
@@ -429,7 +444,7 @@ class Cache implements ICache {
|
|
|
429
444
|
* @param imageId - image Id to check
|
|
430
445
|
* @returns boolean
|
|
431
446
|
*/
|
|
432
|
-
public
|
|
447
|
+
public isLoaded(imageId: string): boolean {
|
|
433
448
|
const cachedImage = this._imageCache.get(imageId);
|
|
434
449
|
|
|
435
450
|
if (!cachedImage) {
|
|
@@ -151,12 +151,12 @@ export class ImageVolume implements IImageVolume {
|
|
|
151
151
|
*/
|
|
152
152
|
destroy(): void {
|
|
153
153
|
// TODO: GPU memory associated with volume is not cleared.
|
|
154
|
-
this.vtkOpenGLTexture.releaseGraphicsResources();
|
|
155
|
-
this.vtkOpenGLTexture.destroyTexture();
|
|
156
|
-
this.vtkOpenGLTexture.delete();
|
|
157
154
|
this.imageData.delete();
|
|
158
155
|
this.imageData = null;
|
|
159
156
|
this.scalarData = null;
|
|
157
|
+
|
|
158
|
+
this.vtkOpenGLTexture.releaseGraphicsResources();
|
|
159
|
+
this.vtkOpenGLTexture.delete();
|
|
160
160
|
}
|
|
161
161
|
}
|
|
162
162
|
|
package/src/init.ts
CHANGED
|
@@ -100,7 +100,7 @@ function hasSharedArrayBuffer() {
|
|
|
100
100
|
* @returns A promise that resolves to true cornerstone has been initialized successfully.
|
|
101
101
|
* @category Initialization
|
|
102
102
|
*/
|
|
103
|
-
async function init(configuration =
|
|
103
|
+
async function init(configuration = config): Promise<boolean> {
|
|
104
104
|
if (csRenderInitialized) {
|
|
105
105
|
return csRenderInitialized;
|
|
106
106
|
}
|
|
@@ -132,7 +132,7 @@ let unknownVolumeLoader;
|
|
|
132
132
|
*/
|
|
133
133
|
function loadVolumeFromVolumeLoader(
|
|
134
134
|
volumeId: string,
|
|
135
|
-
options
|
|
135
|
+
options?: VolumeLoaderOptions
|
|
136
136
|
): Types.IVolumeLoadObject {
|
|
137
137
|
const colonIndex = volumeId.indexOf(':');
|
|
138
138
|
const scheme = volumeId.substring(0, colonIndex);
|
|
@@ -210,7 +210,7 @@ export function loadVolume(
|
|
|
210
210
|
*/
|
|
211
211
|
export async function createAndCacheVolume(
|
|
212
212
|
volumeId: string,
|
|
213
|
-
options
|
|
213
|
+
options?: VolumeLoaderOptions
|
|
214
214
|
): Promise<Record<string, any>> {
|
|
215
215
|
if (volumeId === undefined) {
|
|
216
216
|
throw new Error(
|
package/src/types/IImage.ts
CHANGED
|
@@ -72,6 +72,8 @@ interface IImage {
|
|
|
72
72
|
sliceThickness?: number;
|
|
73
73
|
/** whether image pixels are inverted in color */
|
|
74
74
|
invert: boolean;
|
|
75
|
+
/** image photometric interpretation */
|
|
76
|
+
photometricInterpretation?: string;
|
|
75
77
|
/** image size in number of bytes */
|
|
76
78
|
sizeInBytes: number;
|
|
77
79
|
/** CPU: custom modality LUT for image */
|
|
@@ -91,6 +93,8 @@ interface IImage {
|
|
|
91
93
|
suvbwToSuvbsa?: number;
|
|
92
94
|
};
|
|
93
95
|
};
|
|
96
|
+
loadTimeInMS?: number;
|
|
97
|
+
decodeTimeInMS?: number;
|
|
94
98
|
/** CPU: image statistics for rendering */
|
|
95
99
|
stats?: {
|
|
96
100
|
lastStoredPixelDataToCanvasImageDataTime?: number;
|
|
@@ -28,6 +28,10 @@ export default interface IVolumeViewport extends IViewport {
|
|
|
28
28
|
* projected onto the `Viewport`'s `canvas`.
|
|
29
29
|
*/
|
|
30
30
|
worldToCanvas: (worldPos: Point3) => Point2;
|
|
31
|
+
/**
|
|
32
|
+
* Returns the list of image Ids for the current viewport
|
|
33
|
+
*/
|
|
34
|
+
getImageIds: (volumeId?: string) => string[];
|
|
31
35
|
/**
|
|
32
36
|
* Uses viewport camera and volume actor to decide if the viewport
|
|
33
37
|
* is looking at the volume in the direction of acquisition (imageIds).
|
|
@@ -138,4 +142,8 @@ export default interface IVolumeViewport extends IViewport {
|
|
|
138
142
|
getImageData(volumeId?: string): IImageData | undefined;
|
|
139
143
|
|
|
140
144
|
setOrientation(orientation: OrientationAxis): void;
|
|
145
|
+
/**
|
|
146
|
+
* Reset the viewport properties to the default values
|
|
147
|
+
*/
|
|
148
|
+
resetProperties(volumeId?: string): void;
|
|
141
149
|
}
|
package/src/types/Mat3.ts
CHANGED
|
@@ -1,16 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* This represents a 3x3 matrix of numbers
|
|
3
3
|
*/
|
|
4
|
-
type Mat3 =
|
|
5
|
-
number,
|
|
6
|
-
|
|
7
|
-
number,
|
|
8
|
-
number,
|
|
9
|
-
number,
|
|
10
|
-
number,
|
|
11
|
-
number,
|
|
12
|
-
number,
|
|
13
|
-
number
|
|
14
|
-
];
|
|
4
|
+
type Mat3 =
|
|
5
|
+
| [number, number, number, number, number, number, number, number, number]
|
|
6
|
+
| Float32Array;
|
|
15
7
|
|
|
16
8
|
export default Mat3;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { VOILUTFunctionType } from '../enums';
|
|
1
|
+
import { InterpolationType, VOILUTFunctionType } from '../enums';
|
|
2
2
|
import { VOIRange } from './voi';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -11,6 +11,8 @@ type ViewportProperties = {
|
|
|
11
11
|
VOILUTFunction?: VOILUTFunctionType;
|
|
12
12
|
/** invert flag - whether the image is inverted */
|
|
13
13
|
invert?: boolean;
|
|
14
|
+
/** interpolation type */
|
|
15
|
+
interpolationType?: InterpolationType;
|
|
14
16
|
};
|
|
15
17
|
|
|
16
18
|
export type { ViewportProperties };
|
package/src/types/index.ts
CHANGED
|
@@ -81,6 +81,7 @@ import type { ViewportProperties } from './ViewportProperties';
|
|
|
81
81
|
import type { PixelDataTypedArray } from './PixelDataTypedArray';
|
|
82
82
|
import type { ImagePixelModule } from './ImagePixelModule';
|
|
83
83
|
import type { ImagePlaneModule } from './ImagePlaneModule';
|
|
84
|
+
import type { AffineMatrix } from './AffineMatrix';
|
|
84
85
|
|
|
85
86
|
export type {
|
|
86
87
|
// config
|
|
@@ -173,4 +174,5 @@ export type {
|
|
|
173
174
|
PixelDataTypedArray,
|
|
174
175
|
ImagePixelModule,
|
|
175
176
|
ImagePlaneModule,
|
|
177
|
+
AffineMatrix,
|
|
176
178
|
};
|