@cornerstonejs/core 0.43.0 → 0.44.0
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.js +1 -1
- package/dist/cjs/RenderingEngine/BaseVolumeViewport.js.map +1 -1
- package/dist/cjs/RenderingEngine/StackViewport.d.ts +6 -2
- package/dist/cjs/RenderingEngine/StackViewport.js +95 -68
- package/dist/cjs/RenderingEngine/StackViewport.js.map +1 -1
- package/dist/cjs/RenderingEngine/Viewport.d.ts +2 -1
- package/dist/cjs/RenderingEngine/Viewport.js +1 -1
- package/dist/cjs/RenderingEngine/Viewport.js.map +1 -1
- package/dist/cjs/RenderingEngine/helpers/cpuFallback/rendering/renderColorImage.js +1 -1
- package/dist/cjs/index.d.ts +2 -2
- package/dist/cjs/index.js +2 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/init.d.ts +2 -1
- package/dist/cjs/init.js +18 -13
- package/dist/cjs/init.js.map +1 -1
- package/dist/cjs/types/IImage.d.ts +4 -3
- package/dist/cjs/types/IViewport.d.ts +1 -0
- package/dist/cjs/utilities/calibratedPixelSpacingMetadataProvider.d.ts +7 -2
- package/dist/cjs/utilities/calibratedPixelSpacingMetadataProvider.js +0 -3
- package/dist/cjs/utilities/calibratedPixelSpacingMetadataProvider.js.map +1 -1
- package/dist/cjs/utilities/loadImageToCanvas.js +1 -0
- package/dist/cjs/utilities/loadImageToCanvas.js.map +1 -1
- package/dist/esm/RenderingEngine/BaseVolumeViewport.js +1 -1
- package/dist/esm/RenderingEngine/BaseVolumeViewport.js.map +1 -1
- package/dist/esm/RenderingEngine/StackViewport.d.ts +6 -2
- package/dist/esm/RenderingEngine/StackViewport.js +99 -69
- package/dist/esm/RenderingEngine/StackViewport.js.map +1 -1
- package/dist/esm/RenderingEngine/Viewport.d.ts +2 -1
- package/dist/esm/RenderingEngine/Viewport.js +1 -1
- package/dist/esm/RenderingEngine/Viewport.js.map +1 -1
- package/dist/esm/RenderingEngine/helpers/cpuFallback/rendering/renderColorImage.js +1 -1
- package/dist/esm/index.d.ts +2 -2
- package/dist/esm/index.js +2 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/init.d.ts +2 -1
- package/dist/esm/init.js +17 -13
- package/dist/esm/init.js.map +1 -1
- package/dist/esm/types/IImage.d.ts +4 -3
- package/dist/esm/types/IViewport.d.ts +1 -0
- package/dist/esm/utilities/calibratedPixelSpacingMetadataProvider.d.ts +7 -2
- package/dist/esm/utilities/calibratedPixelSpacingMetadataProvider.js +0 -3
- package/dist/esm/utilities/calibratedPixelSpacingMetadataProvider.js.map +1 -1
- package/dist/esm/utilities/loadImageToCanvas.js +1 -0
- package/dist/esm/utilities/loadImageToCanvas.js.map +1 -1
- package/dist/umd/index.js +1 -1
- package/dist/umd/index.js.map +1 -1
- package/package.json +4 -4
- package/src/RenderingEngine/BaseVolumeViewport.ts +1 -1
- package/src/RenderingEngine/StackViewport.ts +165 -92
- package/src/RenderingEngine/Viewport.ts +2 -1
- package/src/RenderingEngine/helpers/cpuFallback/rendering/renderColorImage.ts +1 -1
- package/src/index.ts +3 -1
- package/src/init.ts +42 -14
- package/src/types/IImage.ts +11 -3
- package/src/types/IViewport.ts +1 -0
- package/src/utilities/calibratedPixelSpacingMetadataProvider.ts +10 -6
- package/src/utilities/loadImageToCanvas.ts +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cornerstonejs/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.44.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "dist/umd/index.js",
|
|
6
6
|
"types": "dist/esm/index.d.ts",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"webpack:watch": "webpack --mode development --progress --watch --config ./.webpack/webpack.dev.js"
|
|
28
28
|
},
|
|
29
29
|
"peerDependencies": {
|
|
30
|
-
"@kitware/vtk.js": "
|
|
30
|
+
"@kitware/vtk.js": "27.3.1",
|
|
31
31
|
"gl-matrix": "^3.4.3"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"lodash.clonedeep": "4.5.0"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
|
-
"@kitware/vtk.js": "
|
|
38
|
+
"@kitware/vtk.js": "27.3.1",
|
|
39
39
|
"detect-gpu": "^4.0.45",
|
|
40
40
|
"gl-matrix": "^3.4.3",
|
|
41
41
|
"resemblejs": "^4.1.0"
|
|
@@ -51,5 +51,5 @@
|
|
|
51
51
|
"type": "individual",
|
|
52
52
|
"url": "https://ohif.org/donate"
|
|
53
53
|
},
|
|
54
|
-
"gitHead": "
|
|
54
|
+
"gitHead": "06ba42597fb76be663ec565463e8ef4b2ac968c8"
|
|
55
55
|
}
|
|
@@ -63,7 +63,7 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
|
|
|
63
63
|
super(props);
|
|
64
64
|
|
|
65
65
|
this.useCPURendering = getShouldUseCPURendering();
|
|
66
|
-
this.use16BitTexture = this.
|
|
66
|
+
this.use16BitTexture = this._shouldUseNativeDataType();
|
|
67
67
|
|
|
68
68
|
if (this.useCPURendering) {
|
|
69
69
|
throw new Error(
|
|
@@ -56,7 +56,7 @@ import resize from './helpers/cpuFallback/rendering/resize';
|
|
|
56
56
|
|
|
57
57
|
import resetCamera from './helpers/cpuFallback/rendering/resetCamera';
|
|
58
58
|
import { Transform } from './helpers/cpuFallback/rendering/transform';
|
|
59
|
-
import { getShouldUseCPURendering } from '../init';
|
|
59
|
+
import { getConfiguration, getShouldUseCPURendering } from '../init';
|
|
60
60
|
import RequestType from '../enums/RequestType';
|
|
61
61
|
import {
|
|
62
62
|
StackViewportNewStackEventDetail,
|
|
@@ -66,7 +66,6 @@ import {
|
|
|
66
66
|
import cache from '../cache';
|
|
67
67
|
import correctShift from './helpers/cpuFallback/rendering/correctShift';
|
|
68
68
|
import { ImageActor } from '../types/IActor';
|
|
69
|
-
import isRgbaSourceRgbDest from './helpers/isRgbaSourceRgbDest';
|
|
70
69
|
import createLinearRGBTransferFunction from '../utilities/createLinearRGBTransferFunction';
|
|
71
70
|
|
|
72
71
|
const EPSILON = 1; // Slice Thickness
|
|
@@ -157,7 +156,12 @@ class StackViewport extends Viewport implements IStackViewport {
|
|
|
157
156
|
private _cpuFallbackEnabledElement?: CPUFallbackEnabledElement;
|
|
158
157
|
// CPU fallback
|
|
159
158
|
private useCPURendering: boolean;
|
|
160
|
-
|
|
159
|
+
// Since WebGL natively supports 8 bit int and Float32, we should check if
|
|
160
|
+
// extra configuration flags has been set to use native data type
|
|
161
|
+
// which would save a lot of memory and speed up rendering but it is not
|
|
162
|
+
// yet widely supported in all hardwares. This feature can be turned on
|
|
163
|
+
// by setting useNorm16Texture or preferSizeOverAccuracy in the configuration
|
|
164
|
+
private useNativeDataType = false;
|
|
161
165
|
private cpuImagePixelData: number[];
|
|
162
166
|
private cpuRenderingInvalidated: boolean;
|
|
163
167
|
private csImage: IImage;
|
|
@@ -178,34 +182,12 @@ class StackViewport extends Viewport implements IStackViewport {
|
|
|
178
182
|
this.scaling = {};
|
|
179
183
|
this.modality = null;
|
|
180
184
|
this.useCPURendering = getShouldUseCPURendering();
|
|
181
|
-
this.
|
|
185
|
+
this.useNativeDataType = this._shouldUseNativeDataType();
|
|
182
186
|
this._configureRenderingPipeline();
|
|
183
187
|
|
|
184
|
-
|
|
185
|
-
this.
|
|
186
|
-
|
|
187
|
-
renderingTools: {},
|
|
188
|
-
transform: new Transform(),
|
|
189
|
-
viewport: { rotation: 0 },
|
|
190
|
-
};
|
|
191
|
-
} else {
|
|
192
|
-
const renderer = this.getRenderer();
|
|
193
|
-
const camera = vtkCamera.newInstance();
|
|
194
|
-
renderer.setActiveCamera(camera);
|
|
195
|
-
|
|
196
|
-
const viewPlaneNormal = <Point3>[0, 0, -1];
|
|
197
|
-
this.initialViewUp = <Point3>[0, -1, 0];
|
|
198
|
-
|
|
199
|
-
camera.setDirectionOfProjection(
|
|
200
|
-
-viewPlaneNormal[0],
|
|
201
|
-
-viewPlaneNormal[1],
|
|
202
|
-
-viewPlaneNormal[2]
|
|
203
|
-
);
|
|
204
|
-
camera.setViewUp(...this.initialViewUp);
|
|
205
|
-
camera.setParallelProjection(true);
|
|
206
|
-
camera.setThicknessFromFocalPoint(0.1);
|
|
207
|
-
camera.setFreezeFocalPoint(true);
|
|
208
|
-
}
|
|
188
|
+
this.useCPURendering
|
|
189
|
+
? this._resetCPUFallbackElement()
|
|
190
|
+
: this._resetGPUViewport();
|
|
209
191
|
|
|
210
192
|
this.imageIds = [];
|
|
211
193
|
this.currentImageIdIndex = 0;
|
|
@@ -216,21 +198,60 @@ class StackViewport extends Viewport implements IStackViewport {
|
|
|
216
198
|
this.initializeElementDisabledHandler();
|
|
217
199
|
}
|
|
218
200
|
|
|
201
|
+
public setUseCPURendering(value: boolean) {
|
|
202
|
+
this.useCPURendering = value;
|
|
203
|
+
this._configureRenderingPipeline();
|
|
204
|
+
}
|
|
205
|
+
|
|
219
206
|
static get useCustomRenderingPipeline(): boolean {
|
|
220
207
|
return getShouldUseCPURendering();
|
|
221
208
|
}
|
|
222
209
|
|
|
223
|
-
public
|
|
224
|
-
this.useCPURendering = value;
|
|
210
|
+
public updateRenderingPipeline = () => {
|
|
225
211
|
this._configureRenderingPipeline();
|
|
226
|
-
}
|
|
212
|
+
};
|
|
227
213
|
|
|
228
214
|
private _configureRenderingPipeline() {
|
|
215
|
+
this.useNativeDataType = this._shouldUseNativeDataType();
|
|
216
|
+
this.useCPURendering = getShouldUseCPURendering();
|
|
217
|
+
|
|
229
218
|
for (const [funcName, functions] of Object.entries(
|
|
230
219
|
this.renderingPipelineFunctions
|
|
231
220
|
)) {
|
|
232
221
|
this[funcName] = this.useCPURendering ? functions.cpu : functions.gpu;
|
|
233
222
|
}
|
|
223
|
+
|
|
224
|
+
this.useCPURendering
|
|
225
|
+
? this._resetCPUFallbackElement()
|
|
226
|
+
: this._resetGPUViewport();
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
private _resetCPUFallbackElement() {
|
|
230
|
+
this._cpuFallbackEnabledElement = {
|
|
231
|
+
canvas: this.canvas,
|
|
232
|
+
renderingTools: {},
|
|
233
|
+
transform: new Transform(),
|
|
234
|
+
viewport: { rotation: 0 },
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
private _resetGPUViewport() {
|
|
239
|
+
const renderer = this.getRenderer();
|
|
240
|
+
const camera = vtkCamera.newInstance();
|
|
241
|
+
renderer.setActiveCamera(camera);
|
|
242
|
+
|
|
243
|
+
const viewPlaneNormal = <Point3>[0, 0, -1];
|
|
244
|
+
this.initialViewUp = <Point3>[0, -1, 0];
|
|
245
|
+
|
|
246
|
+
camera.setDirectionOfProjection(
|
|
247
|
+
-viewPlaneNormal[0],
|
|
248
|
+
-viewPlaneNormal[1],
|
|
249
|
+
-viewPlaneNormal[2]
|
|
250
|
+
);
|
|
251
|
+
camera.setViewUp(...this.initialViewUp);
|
|
252
|
+
camera.setParallelProjection(true);
|
|
253
|
+
camera.setThicknessFromFocalPoint(0.1);
|
|
254
|
+
camera.setFreezeFocalPoint(true);
|
|
234
255
|
}
|
|
235
256
|
|
|
236
257
|
/**
|
|
@@ -500,6 +521,13 @@ class StackViewport extends Viewport implements IStackViewport {
|
|
|
500
521
|
|
|
501
522
|
actor.setMapper(mapper);
|
|
502
523
|
|
|
524
|
+
const { preferSizeOverAccuracy } = getConfiguration().rendering;
|
|
525
|
+
|
|
526
|
+
if (preferSizeOverAccuracy) {
|
|
527
|
+
// @ts-ignore for now until vtk is updated
|
|
528
|
+
mapper.setPreferSizeOverAccuracy(true);
|
|
529
|
+
}
|
|
530
|
+
|
|
503
531
|
if (imageData.getPointData().getNumberOfComponents() > 1) {
|
|
504
532
|
actor.getProperty().setIndependentComponents(false);
|
|
505
533
|
}
|
|
@@ -584,8 +612,10 @@ class StackViewport extends Viewport implements IStackViewport {
|
|
|
584
612
|
return imagePlaneModule;
|
|
585
613
|
}
|
|
586
614
|
|
|
587
|
-
const
|
|
588
|
-
|
|
615
|
+
const {
|
|
616
|
+
rowPixelSpacing: calibratedRowSpacing,
|
|
617
|
+
columnPixelSpacing: calibratedColumnSpacing,
|
|
618
|
+
} = calibratedPixelSpacing;
|
|
589
619
|
|
|
590
620
|
// Todo: This is necessary in general, but breaks an edge case when an image
|
|
591
621
|
// is calibrated to some other spacing, and it gets calibrated BACK to the
|
|
@@ -624,7 +654,9 @@ class StackViewport extends Viewport implements IStackViewport {
|
|
|
624
654
|
calibratedColumnSpacing / imagePlaneModule.columnPixelSpacing,
|
|
625
655
|
};
|
|
626
656
|
|
|
627
|
-
// modify
|
|
657
|
+
// modify the calibration object to store the actual updated values applied
|
|
658
|
+
calibratedPixelSpacing.appliedSpacing = calibratedPixelSpacing;
|
|
659
|
+
// This updates the render copy
|
|
628
660
|
imagePlaneModule.rowPixelSpacing = calibratedRowSpacing;
|
|
629
661
|
imagePlaneModule.columnPixelSpacing = calibratedColumnSpacing;
|
|
630
662
|
return imagePlaneModule;
|
|
@@ -634,6 +666,8 @@ class StackViewport extends Viewport implements IStackViewport {
|
|
|
634
666
|
const { imageData } = imageDataMetadata;
|
|
635
667
|
const [columnPixelSpacing, rowPixelSpacing] = imageData.getSpacing();
|
|
636
668
|
|
|
669
|
+
// modify the calibration object to store the actual updated values applied
|
|
670
|
+
calibratedPixelSpacing.appliedSpacing = calibratedPixelSpacing;
|
|
637
671
|
imagePlaneModule.rowPixelSpacing = calibratedRowSpacing;
|
|
638
672
|
imagePlaneModule.columnPixelSpacing = calibratedColumnSpacing;
|
|
639
673
|
|
|
@@ -1424,32 +1458,10 @@ class StackViewport extends Viewport implements IStackViewport {
|
|
|
1424
1458
|
direction,
|
|
1425
1459
|
dimensions,
|
|
1426
1460
|
spacing,
|
|
1427
|
-
bitsAllocated,
|
|
1428
1461
|
numComps,
|
|
1429
|
-
|
|
1430
|
-
TypedArray,
|
|
1462
|
+
pixelArray,
|
|
1431
1463
|
}): void {
|
|
1432
|
-
|
|
1433
|
-
switch (bitsAllocated) {
|
|
1434
|
-
case 8:
|
|
1435
|
-
pixelArray = new Uint8Array(numVoxels * numComps);
|
|
1436
|
-
break;
|
|
1437
|
-
case 16:
|
|
1438
|
-
if (this.use16BitTexture) {
|
|
1439
|
-
pixelArray = new TypedArray(numVoxels * numComps);
|
|
1440
|
-
} else {
|
|
1441
|
-
pixelArray = new Float32Array(numVoxels * numComps);
|
|
1442
|
-
}
|
|
1443
|
-
|
|
1444
|
-
break;
|
|
1445
|
-
case 24:
|
|
1446
|
-
pixelArray = new Uint8Array(numVoxels * 3 * numComps);
|
|
1447
|
-
|
|
1448
|
-
break;
|
|
1449
|
-
default:
|
|
1450
|
-
console.log('bit allocation not implemented');
|
|
1451
|
-
}
|
|
1452
|
-
|
|
1464
|
+
// Todo: I guess nothing should be done for use16bit?
|
|
1453
1465
|
const scalarArray = vtkDataArray.newInstance({
|
|
1454
1466
|
name: 'Pixels',
|
|
1455
1467
|
numberOfComponents: numComps,
|
|
@@ -1550,7 +1562,7 @@ class StackViewport extends Viewport implements IStackViewport {
|
|
|
1550
1562
|
yVoxels === image.rows &&
|
|
1551
1563
|
isEqual(imagePlaneModule.rowCosines, <Point3>rowCosines) &&
|
|
1552
1564
|
isEqual(imagePlaneModule.columnCosines, <Point3>columnCosines) &&
|
|
1553
|
-
(!this.
|
|
1565
|
+
(!this.useNativeDataType ||
|
|
1554
1566
|
dataType === image.getPixelData().constructor.name)
|
|
1555
1567
|
);
|
|
1556
1568
|
}
|
|
@@ -1571,8 +1583,12 @@ class StackViewport extends Viewport implements IStackViewport {
|
|
|
1571
1583
|
|
|
1572
1584
|
this._imageData.setOrigin(origin);
|
|
1573
1585
|
|
|
1574
|
-
//
|
|
1575
|
-
//
|
|
1586
|
+
// Update the pixel data in the vtkImageData object with the pixelData
|
|
1587
|
+
// from the loaded Cornerstone image
|
|
1588
|
+
this._updatePixelData(image);
|
|
1589
|
+
}
|
|
1590
|
+
|
|
1591
|
+
private _updatePixelData(image: IImage) {
|
|
1576
1592
|
const pixelData = image.getPixelData();
|
|
1577
1593
|
const scalars = this._imageData.getPointData().getScalars();
|
|
1578
1594
|
const scalarData = scalars.getData() as
|
|
@@ -1581,24 +1597,21 @@ class StackViewport extends Viewport implements IStackViewport {
|
|
|
1581
1597
|
| Uint16Array
|
|
1582
1598
|
| Int16Array;
|
|
1583
1599
|
|
|
1584
|
-
if
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
let rgbIndex = 0;
|
|
1594
|
-
let index = 0;
|
|
1595
|
-
|
|
1596
|
-
for (let i = 0; i < numPixels; i++) {
|
|
1597
|
-
scalarData[index++] = pixelData[rgbIndex++]; // red
|
|
1598
|
-
scalarData[index++] = pixelData[rgbIndex++]; // green
|
|
1599
|
-
scalarData[index++] = pixelData[rgbIndex++]; // blue
|
|
1600
|
-
rgbIndex++; // skip alpha
|
|
1600
|
+
// if the color image is loaded with CPU previously, it loads it
|
|
1601
|
+
// with RGBA, and here we need to remove the A channel from the
|
|
1602
|
+
// pixel data.
|
|
1603
|
+
if (image.color && image.rgba) {
|
|
1604
|
+
const newPixelData = new Uint8Array(image.columns * image.rows * 3);
|
|
1605
|
+
for (let i = 0; i < image.columns * image.rows; i++) {
|
|
1606
|
+
newPixelData[i * 3] = pixelData[i * 4];
|
|
1607
|
+
newPixelData[i * 3 + 1] = pixelData[i * 4 + 1];
|
|
1608
|
+
newPixelData[i * 3 + 2] = pixelData[i * 4 + 2];
|
|
1601
1609
|
}
|
|
1610
|
+
// modify the image object to have the correct pixel data for later
|
|
1611
|
+
// use.
|
|
1612
|
+
image.rgba = false;
|
|
1613
|
+
image.getPixelData = () => newPixelData;
|
|
1614
|
+
scalarData.set(newPixelData);
|
|
1602
1615
|
} else {
|
|
1603
1616
|
scalarData.set(pixelData);
|
|
1604
1617
|
}
|
|
@@ -1645,6 +1658,50 @@ class StackViewport extends Viewport implements IStackViewport {
|
|
|
1645
1658
|
return;
|
|
1646
1659
|
}
|
|
1647
1660
|
|
|
1661
|
+
const pixelData = image.getPixelData();
|
|
1662
|
+
|
|
1663
|
+
// handle the case where the pixelData is a Float32Array
|
|
1664
|
+
// CPU path cannot handle it, it should be converted to Uint16Array
|
|
1665
|
+
// and via the Modality LUT we can display it properly
|
|
1666
|
+
if (pixelData instanceof Float32Array) {
|
|
1667
|
+
const floatMinMax = {
|
|
1668
|
+
min: image.maxPixelValue,
|
|
1669
|
+
max: image.minPixelValue,
|
|
1670
|
+
};
|
|
1671
|
+
const floatRange = Math.abs(floatMinMax.max - floatMinMax.min);
|
|
1672
|
+
const intRange = 65535;
|
|
1673
|
+
const slope = floatRange / intRange;
|
|
1674
|
+
const intercept = floatMinMax.min;
|
|
1675
|
+
const numPixels = pixelData.length;
|
|
1676
|
+
const intPixelData = new Uint16Array(numPixels);
|
|
1677
|
+
|
|
1678
|
+
let min = 65535;
|
|
1679
|
+
|
|
1680
|
+
let max = 0;
|
|
1681
|
+
|
|
1682
|
+
for (let i = 0; i < numPixels; i++) {
|
|
1683
|
+
const rescaledPixel = Math.floor(
|
|
1684
|
+
(pixelData[i] - intercept) / slope
|
|
1685
|
+
);
|
|
1686
|
+
|
|
1687
|
+
intPixelData[i] = rescaledPixel;
|
|
1688
|
+
min = Math.min(min, rescaledPixel);
|
|
1689
|
+
max = Math.max(max, rescaledPixel);
|
|
1690
|
+
}
|
|
1691
|
+
|
|
1692
|
+
// reset the properties since basically the image has changed
|
|
1693
|
+
image.minPixelValue = min;
|
|
1694
|
+
image.maxPixelValue = max;
|
|
1695
|
+
image.slope = slope;
|
|
1696
|
+
image.intercept = intercept;
|
|
1697
|
+
image.getPixelData = () => intPixelData;
|
|
1698
|
+
|
|
1699
|
+
image.preScale = {
|
|
1700
|
+
...image.preScale,
|
|
1701
|
+
scaled: false,
|
|
1702
|
+
};
|
|
1703
|
+
}
|
|
1704
|
+
|
|
1648
1705
|
image.isPreScaled = image.preScale?.scaled;
|
|
1649
1706
|
this.csImage = image;
|
|
1650
1707
|
|
|
@@ -1667,6 +1724,12 @@ class StackViewport extends Viewport implements IStackViewport {
|
|
|
1667
1724
|
this._cpuFallbackEnabledElement.viewport.colormap
|
|
1668
1725
|
);
|
|
1669
1726
|
|
|
1727
|
+
const { windowCenter, windowWidth } = viewport.voi;
|
|
1728
|
+
this.voiRange = windowLevelUtil.toLowHighRange(
|
|
1729
|
+
windowWidth,
|
|
1730
|
+
windowCenter
|
|
1731
|
+
);
|
|
1732
|
+
|
|
1670
1733
|
this._cpuFallbackEnabledElement.image = image;
|
|
1671
1734
|
this._cpuFallbackEnabledElement.metadata = {
|
|
1672
1735
|
...metadata,
|
|
@@ -1741,9 +1804,6 @@ class StackViewport extends Viewport implements IStackViewport {
|
|
|
1741
1804
|
const requestType = RequestType.Interaction;
|
|
1742
1805
|
const additionalDetails = { imageId };
|
|
1743
1806
|
const options = {
|
|
1744
|
-
targetBuffer: {
|
|
1745
|
-
type: this.use16BitTexture ? undefined : 'Float32Array',
|
|
1746
|
-
},
|
|
1747
1807
|
preScale: {
|
|
1748
1808
|
enabled: true,
|
|
1749
1809
|
},
|
|
@@ -1827,17 +1887,19 @@ class StackViewport extends Viewport implements IStackViewport {
|
|
|
1827
1887
|
}
|
|
1828
1888
|
|
|
1829
1889
|
/**
|
|
1830
|
-
*
|
|
1831
|
-
* is provided. When CSWIL is initialized,
|
|
1832
|
-
* the settings of cornerstone3D (either preferSizeOverAccuracy
|
|
1833
|
-
* textures need to be enabled)
|
|
1890
|
+
* If use16bittexture is specified, the CSWIL will automatically choose the
|
|
1891
|
+
* array type when no targetBuffer is provided. When CSWIL is initialized,
|
|
1892
|
+
* the use16bit should match the settings of cornerstone3D (either preferSizeOverAccuracy
|
|
1893
|
+
* or norm16 textures need to be enabled)
|
|
1894
|
+
*
|
|
1895
|
+
* If use16bittexture is not specified, we force the Float32Array for now
|
|
1834
1896
|
*/
|
|
1835
1897
|
const priority = -5;
|
|
1836
1898
|
const requestType = RequestType.Interaction;
|
|
1837
1899
|
const additionalDetails = { imageId };
|
|
1838
1900
|
const options = {
|
|
1839
1901
|
targetBuffer: {
|
|
1840
|
-
type: this.
|
|
1902
|
+
type: this.useNativeDataType ? undefined : 'Float32Array',
|
|
1841
1903
|
},
|
|
1842
1904
|
preScale: {
|
|
1843
1905
|
enabled: true,
|
|
@@ -1946,9 +2008,7 @@ class StackViewport extends Viewport implements IStackViewport {
|
|
|
1946
2008
|
direction,
|
|
1947
2009
|
dimensions,
|
|
1948
2010
|
spacing,
|
|
1949
|
-
bitsAllocated,
|
|
1950
2011
|
numComps,
|
|
1951
|
-
numVoxels,
|
|
1952
2012
|
imagePixelModule,
|
|
1953
2013
|
} = this._getImageDataMetadata(image);
|
|
1954
2014
|
|
|
@@ -1959,10 +2019,8 @@ class StackViewport extends Viewport implements IStackViewport {
|
|
|
1959
2019
|
direction,
|
|
1960
2020
|
dimensions,
|
|
1961
2021
|
spacing,
|
|
1962
|
-
bitsAllocated,
|
|
1963
2022
|
numComps,
|
|
1964
|
-
|
|
1965
|
-
TypedArray: image.getPixelData().constructor,
|
|
2023
|
+
pixelArray: image.getPixelData(),
|
|
1966
2024
|
});
|
|
1967
2025
|
|
|
1968
2026
|
// Set the scalar data of the vtkImageData object from the Cornerstone
|
|
@@ -2574,10 +2632,25 @@ class StackViewport extends Viewport implements IStackViewport {
|
|
|
2574
2632
|
private _getImagePlaneModule(imageId: string): ImagePlaneModule {
|
|
2575
2633
|
const imagePlaneModule = metaData.get('imagePlaneModule', imageId);
|
|
2576
2634
|
|
|
2635
|
+
const calibratedPixelSpacing = metaData.get(
|
|
2636
|
+
'calibratedPixelSpacing',
|
|
2637
|
+
imageId
|
|
2638
|
+
);
|
|
2639
|
+
|
|
2577
2640
|
const newImagePlaneModule: ImagePlaneModule = {
|
|
2578
2641
|
...imagePlaneModule,
|
|
2579
2642
|
};
|
|
2580
2643
|
|
|
2644
|
+
if (calibratedPixelSpacing?.appliedSpacing) {
|
|
2645
|
+
// Over-ride the image plane module spacing, as the measurement data
|
|
2646
|
+
// has already been created with the calibrated spacing provided from
|
|
2647
|
+
// down below inside calibrateIfNecessary
|
|
2648
|
+
const { rowPixelSpacing, columnPixelSpacing } =
|
|
2649
|
+
calibratedPixelSpacing.appliedSpacing;
|
|
2650
|
+
newImagePlaneModule.rowPixelSpacing = rowPixelSpacing;
|
|
2651
|
+
newImagePlaneModule.columnPixelSpacing = columnPixelSpacing;
|
|
2652
|
+
}
|
|
2653
|
+
|
|
2581
2654
|
if (!newImagePlaneModule.columnPixelSpacing) {
|
|
2582
2655
|
newImagePlaneModule.columnPixelSpacing = 1;
|
|
2583
2656
|
this.hasPixelSpacing = false;
|
|
@@ -111,6 +111,7 @@ class Viewport implements IViewport {
|
|
|
111
111
|
customRenderViewportToCanvas: () => unknown;
|
|
112
112
|
resize: () => void;
|
|
113
113
|
getProperties: () => void;
|
|
114
|
+
updateRenderingPipeline: () => void;
|
|
114
115
|
|
|
115
116
|
static get useCustomRenderingPipeline(): boolean {
|
|
116
117
|
return false;
|
|
@@ -1222,7 +1223,7 @@ class Viewport implements IViewport {
|
|
|
1222
1223
|
return { widthWorld: maxX - minX, heightWorld: maxY - minY };
|
|
1223
1224
|
}
|
|
1224
1225
|
|
|
1225
|
-
protected
|
|
1226
|
+
protected _shouldUseNativeDataType() {
|
|
1226
1227
|
const { useNorm16Texture, preferSizeOverAccuracy } =
|
|
1227
1228
|
getConfiguration().rendering;
|
|
1228
1229
|
return useNorm16Texture || preferSizeOverAccuracy;
|
|
@@ -75,7 +75,7 @@ function getRenderCanvas(
|
|
|
75
75
|
// Fast drawing
|
|
76
76
|
if (
|
|
77
77
|
enabledElement.viewport.voi.windowWidth === 255 &&
|
|
78
|
-
enabledElement.viewport.voi.windowCenter ===
|
|
78
|
+
enabledElement.viewport.voi.windowCenter === 127 &&
|
|
79
79
|
enabledElement.viewport.invert === false &&
|
|
80
80
|
image.getCanvas &&
|
|
81
81
|
image.getCanvas()
|
package/src/index.ts
CHANGED
|
@@ -33,6 +33,7 @@ import {
|
|
|
33
33
|
getShouldUseSharedArrayBuffer,
|
|
34
34
|
isCornerstoneInitialized,
|
|
35
35
|
setUseCPURendering,
|
|
36
|
+
setPreferSizeOverAccuracy,
|
|
36
37
|
setUseSharedArrayBuffer,
|
|
37
38
|
resetUseCPURendering,
|
|
38
39
|
resetUseSharedArrayBuffer,
|
|
@@ -70,7 +71,7 @@ export {
|
|
|
70
71
|
// enums
|
|
71
72
|
Enums,
|
|
72
73
|
CONSTANTS,
|
|
73
|
-
Events as EVENTS, //
|
|
74
|
+
Events as EVENTS, // CornerstoneDICOMImageLoader uses this, Todo: remove it after fixing wado
|
|
74
75
|
//
|
|
75
76
|
Settings,
|
|
76
77
|
// Rendering Engine
|
|
@@ -113,6 +114,7 @@ export {
|
|
|
113
114
|
// CPU Rendering
|
|
114
115
|
getShouldUseCPURendering,
|
|
115
116
|
setUseCPURendering,
|
|
117
|
+
setPreferSizeOverAccuracy,
|
|
116
118
|
resetUseCPURendering,
|
|
117
119
|
// SharedArrayBuffer
|
|
118
120
|
getShouldUseSharedArrayBuffer,
|
package/src/init.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { getGPUTier } from 'detect-gpu';
|
|
2
2
|
import { SharedArrayBufferModes } from './enums';
|
|
3
|
+
import { getRenderingEngines } from './RenderingEngine/getRenderingEngine';
|
|
3
4
|
let csRenderInitialized = false;
|
|
4
5
|
let useSharedArrayBuffer = true;
|
|
5
6
|
let sharedArrayBufferMode = SharedArrayBufferModes.TRUE;
|
|
@@ -10,8 +11,9 @@ import { Cornerstone3DConfig } from './types';
|
|
|
10
11
|
const defaultConfig = {
|
|
11
12
|
detectGPU: {},
|
|
12
13
|
rendering: {
|
|
13
|
-
preferSizeOverAccuracy: false,
|
|
14
14
|
useCPURendering: false,
|
|
15
|
+
// GPU rendering options
|
|
16
|
+
preferSizeOverAccuracy: false,
|
|
15
17
|
useNorm16Texture: false, // _hasNorm16TextureSupport(),
|
|
16
18
|
strictZSpacingForVolumeViewport: true,
|
|
17
19
|
},
|
|
@@ -22,8 +24,9 @@ const defaultConfig = {
|
|
|
22
24
|
let config = {
|
|
23
25
|
detectGPU: {},
|
|
24
26
|
rendering: {
|
|
25
|
-
preferSizeOverAccuracy: false,
|
|
26
27
|
useCPURendering: false,
|
|
28
|
+
// GPU rendering options
|
|
29
|
+
preferSizeOverAccuracy: false,
|
|
27
30
|
useNorm16Texture: false, // _hasNorm16TextureSupport(),
|
|
28
31
|
strictZSpacingForVolumeViewport: true,
|
|
29
32
|
},
|
|
@@ -68,21 +71,23 @@ function hasSharedArrayBuffer() {
|
|
|
68
71
|
}
|
|
69
72
|
}
|
|
70
73
|
|
|
71
|
-
|
|
72
|
-
|
|
74
|
+
// Todo: commenting this out until proper support for int16 textures
|
|
75
|
+
// are added to browsers, current implementation is buggy
|
|
76
|
+
// function _hasNorm16TextureSupport() {
|
|
77
|
+
// const gl = _getGLContext();
|
|
73
78
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
79
|
+
// if (gl) {
|
|
80
|
+
// const ext = (gl as WebGL2RenderingContext).getExtension(
|
|
81
|
+
// 'EXT_texture_norm16'
|
|
82
|
+
// );
|
|
78
83
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
84
|
+
// if (ext) {
|
|
85
|
+
// return true;
|
|
86
|
+
// }
|
|
87
|
+
// }
|
|
83
88
|
|
|
84
|
-
|
|
85
|
-
}
|
|
89
|
+
// return false;
|
|
90
|
+
// }
|
|
86
91
|
|
|
87
92
|
/**
|
|
88
93
|
* Initialize the cornerstone-core. If the browser has a webgl context and
|
|
@@ -140,6 +145,13 @@ async function init(configuration = {}): Promise<boolean> {
|
|
|
140
145
|
function setUseCPURendering(status: boolean): void {
|
|
141
146
|
config.rendering.useCPURendering = status;
|
|
142
147
|
csRenderInitialized = true;
|
|
148
|
+
_updateRenderingPipelinesForAllViewports();
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function setPreferSizeOverAccuracy(status: boolean): void {
|
|
152
|
+
config.rendering.preferSizeOverAccuracy = status;
|
|
153
|
+
csRenderInitialized = true;
|
|
154
|
+
_updateRenderingPipelinesForAllViewports();
|
|
143
155
|
}
|
|
144
156
|
|
|
145
157
|
/**
|
|
@@ -150,6 +162,7 @@ function setUseCPURendering(status: boolean): void {
|
|
|
150
162
|
*/
|
|
151
163
|
function resetUseCPURendering(): void {
|
|
152
164
|
config.rendering.useCPURendering = !_hasActiveWebGLContext();
|
|
165
|
+
_updateRenderingPipelinesForAllViewports();
|
|
153
166
|
}
|
|
154
167
|
|
|
155
168
|
/**
|
|
@@ -225,6 +238,20 @@ function getConfiguration(): Cornerstone3DConfig {
|
|
|
225
238
|
|
|
226
239
|
function setConfiguration(c: Cornerstone3DConfig) {
|
|
227
240
|
config = c;
|
|
241
|
+
_updateRenderingPipelinesForAllViewports();
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Update rendering pipelines for all viewports in all rendering engines.
|
|
246
|
+
* @returns {void}
|
|
247
|
+
* @category Initialization
|
|
248
|
+
*/
|
|
249
|
+
function _updateRenderingPipelinesForAllViewports(): void {
|
|
250
|
+
getRenderingEngines().forEach((engine) =>
|
|
251
|
+
engine
|
|
252
|
+
.getViewports()
|
|
253
|
+
.forEach((viewport) => viewport.updateRenderingPipeline?.())
|
|
254
|
+
);
|
|
228
255
|
}
|
|
229
256
|
|
|
230
257
|
export {
|
|
@@ -234,6 +261,7 @@ export {
|
|
|
234
261
|
isCornerstoneInitialized,
|
|
235
262
|
setUseCPURendering,
|
|
236
263
|
setUseSharedArrayBuffer,
|
|
264
|
+
setPreferSizeOverAccuracy,
|
|
237
265
|
resetUseCPURendering,
|
|
238
266
|
resetUseSharedArrayBuffer,
|
|
239
267
|
getConfiguration,
|
package/src/types/IImage.ts
CHANGED
|
@@ -2,6 +2,14 @@ import CPUFallbackLUT from './CPUFallbackLUT';
|
|
|
2
2
|
import CPUFallbackColormap from './CPUFallbackColormap';
|
|
3
3
|
import CPUFallbackEnabledElement from './CPUFallbackEnabledElement';
|
|
4
4
|
|
|
5
|
+
type PixelDataTypedArray =
|
|
6
|
+
| Float32Array
|
|
7
|
+
| Int16Array
|
|
8
|
+
| Uint16Array
|
|
9
|
+
| Uint8Array
|
|
10
|
+
| Int8Array
|
|
11
|
+
| Uint8ClampedArray;
|
|
12
|
+
|
|
5
13
|
/**
|
|
6
14
|
* Cornerstone Image interface, it is used for both CPU and GPU rendering
|
|
7
15
|
*/
|
|
@@ -14,9 +22,9 @@ interface IImage {
|
|
|
14
22
|
/** preScale object */
|
|
15
23
|
preScale?: {
|
|
16
24
|
/** boolean flag to indicate whether the image has been scaled */
|
|
17
|
-
scaled
|
|
25
|
+
scaled?: boolean;
|
|
18
26
|
/** scaling parameters */
|
|
19
|
-
scalingParameters
|
|
27
|
+
scalingParameters?: {
|
|
20
28
|
/** modality of the image */
|
|
21
29
|
modality?: string;
|
|
22
30
|
/** rescale slop */
|
|
@@ -42,7 +50,7 @@ interface IImage {
|
|
|
42
50
|
/** voiLUTFunction from metadata */
|
|
43
51
|
voiLUTFunction: string;
|
|
44
52
|
/** function that returns the pixelData as an array */
|
|
45
|
-
getPixelData: () =>
|
|
53
|
+
getPixelData: () => PixelDataTypedArray;
|
|
46
54
|
getCanvas: () => HTMLCanvasElement;
|
|
47
55
|
/** image number of rows */
|
|
48
56
|
rows: number;
|
package/src/types/IViewport.ts
CHANGED