@cornerstonejs/core 4.14.6 → 4.15.1
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/esm/RenderingEngine/BaseVolumeViewport.js +1 -0
- package/dist/esm/cache/classes/BaseStreamingImageVolume.d.ts +4 -4
- package/dist/esm/cache/classes/BaseStreamingImageVolume.js +4 -4
- package/dist/esm/cache/classes/ImageVolume.d.ts +1 -0
- package/dist/esm/cache/classes/StreamingDynamicImageVolume.d.ts +2 -2
- package/dist/esm/index.d.ts +3 -1
- package/dist/esm/index.js +3 -1
- package/dist/esm/loaders/decimatedVolumeLoader.d.ts +14 -0
- package/dist/esm/loaders/decimatedVolumeLoader.js +110 -0
- package/dist/esm/loaders/decimatedVolumeModifiers/applyDecimatedVolumeModifiers.d.ts +3 -0
- package/dist/esm/loaders/decimatedVolumeModifiers/applyDecimatedVolumeModifiers.js +3 -0
- package/dist/esm/loaders/decimatedVolumeModifiers/inPlaneDecimationModifier.d.ts +2 -0
- package/dist/esm/loaders/decimatedVolumeModifiers/inPlaneDecimationModifier.js +36 -0
- package/dist/esm/loaders/decimatedVolumeModifiers/index.d.ts +4 -0
- package/dist/esm/loaders/decimatedVolumeModifiers/index.js +2 -0
- package/dist/esm/loaders/decimatedVolumeModifiers/types.d.ts +17 -0
- package/dist/esm/loaders/decimatedVolumeModifiers/types.js +0 -0
- package/dist/esm/loaders/index.d.ts +2 -1
- package/dist/esm/loaders/index.js +2 -1
- package/dist/esm/loaders/volumeLoader.d.ts +1 -0
- package/dist/esm/utilities/index.d.ts +2 -2
- package/dist/esm/utilities/index.js +2 -2
- package/dist/esm/utilities/splitImageIdsBy4DTags.d.ts +7 -0
- package/dist/esm/utilities/splitImageIdsBy4DTags.js +73 -0
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/package.json +2 -2
|
@@ -28,8 +28,8 @@ export declare class BaseStreamingImageVolume extends ImageVolume implements IIm
|
|
|
28
28
|
getLoaderImageOptions(imageId: string): {
|
|
29
29
|
targetBuffer: {
|
|
30
30
|
type: import("../../types").PixelDataTypedArrayString;
|
|
31
|
-
rows:
|
|
32
|
-
columns:
|
|
31
|
+
rows: number;
|
|
32
|
+
columns: number;
|
|
33
33
|
};
|
|
34
34
|
allowFloatRendering: boolean;
|
|
35
35
|
preScale: {
|
|
@@ -54,8 +54,8 @@ export declare class BaseStreamingImageVolume extends ImageVolume implements IIm
|
|
|
54
54
|
options: {
|
|
55
55
|
targetBuffer: {
|
|
56
56
|
type: import("../../types").PixelDataTypedArrayString;
|
|
57
|
-
rows:
|
|
58
|
-
columns:
|
|
57
|
+
rows: number;
|
|
58
|
+
columns: number;
|
|
59
59
|
};
|
|
60
60
|
allowFloatRendering: boolean;
|
|
61
61
|
preScale: {
|
|
@@ -196,8 +196,8 @@ export class BaseStreamingImageVolume extends ImageVolume {
|
|
|
196
196
|
}
|
|
197
197
|
getLoaderImageOptions(imageId) {
|
|
198
198
|
const { transferSyntaxUID: transferSyntaxUID } = metaData.get('transferSyntax', imageId) || {};
|
|
199
|
-
const
|
|
200
|
-
const
|
|
199
|
+
const targetRows = this.dimensions[1];
|
|
200
|
+
const targetCols = this.dimensions[0];
|
|
201
201
|
const imageIdIndex = this.getImageIdIndex(imageId);
|
|
202
202
|
const modalityLutModule = metaData.get('modalityLutModule', imageId) || {};
|
|
203
203
|
const generalSeriesModule = metaData.get('generalSeriesModule', imageId) || {};
|
|
@@ -230,8 +230,8 @@ export class BaseStreamingImageVolume extends ImageVolume {
|
|
|
230
230
|
}
|
|
231
231
|
const targetBuffer = {
|
|
232
232
|
type: this.dataType,
|
|
233
|
-
rows,
|
|
234
|
-
columns,
|
|
233
|
+
rows: targetRows,
|
|
234
|
+
columns: targetCols,
|
|
235
235
|
};
|
|
236
236
|
return {
|
|
237
237
|
targetBuffer,
|
|
@@ -35,6 +35,7 @@ export declare class ImageVolume {
|
|
|
35
35
|
referencedImageIds?: string[];
|
|
36
36
|
hasPixelSpacing: boolean;
|
|
37
37
|
additionalDetails?: Record<string, unknown>;
|
|
38
|
+
numDimensionGroups: number;
|
|
38
39
|
voxelManager?: IVoxelManager<number> | IVoxelManager<RGB>;
|
|
39
40
|
dataType?: PixelDataTypedArrayString;
|
|
40
41
|
get numTimePoints(): number;
|
|
@@ -27,8 +27,8 @@ export default class StreamingDynamicImageVolume extends BaseStreamingImageVolum
|
|
|
27
27
|
options: {
|
|
28
28
|
targetBuffer: {
|
|
29
29
|
type: import("../../types").PixelDataTypedArrayString;
|
|
30
|
-
rows:
|
|
31
|
-
columns:
|
|
30
|
+
rows: number;
|
|
31
|
+
columns: number;
|
|
32
32
|
};
|
|
33
33
|
allowFloatRendering: boolean;
|
|
34
34
|
preScale: {
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -27,6 +27,7 @@ import * as volumeLoader from './loaders/volumeLoader';
|
|
|
27
27
|
import * as imageLoader from './loaders/imageLoader';
|
|
28
28
|
import * as geometryLoader from './loaders/geometryLoader';
|
|
29
29
|
import ProgressiveRetrieveImages from './loaders/ProgressiveRetrieveImages';
|
|
30
|
+
import { decimatedVolumeLoader } from './loaders/decimatedVolumeLoader';
|
|
30
31
|
import type * as Types from './types';
|
|
31
32
|
import type { IRetrieveConfiguration, IImagesLoader, RetrieveOptions, RetrieveStage, ImageLoadListener } from './types';
|
|
32
33
|
import * as utilities from './utilities';
|
|
@@ -36,5 +37,6 @@ import { cornerstoneStreamingImageVolumeLoader } from './loaders/cornerstoneStre
|
|
|
36
37
|
import { cornerstoneStreamingDynamicImageVolumeLoader } from './loaders/cornerstoneStreamingDynamicImageVolumeLoader';
|
|
37
38
|
import { cornerstoneMeshLoader } from './loaders/cornerstoneMeshLoader';
|
|
38
39
|
import { setVolumesForViewports, addVolumesToViewports, addImageSlicesToViewports } from './RenderingEngine/helpers';
|
|
40
|
+
export * from './loaders/decimatedVolumeLoader';
|
|
39
41
|
export type { Types, IRetrieveConfiguration, RetrieveOptions, RetrieveStage, ImageLoadListener, IImagesLoader, };
|
|
40
|
-
export { init, isCornerstoneInitialized, peerImport, resetInitialization, getConfiguration, setConfiguration, getWebWorkerManager, canRenderFloatTextures, Enums, CONSTANTS, Events as EVENTS, Settings, BaseVolumeViewport, VolumeViewport, VolumeViewport3D, Viewport, StackViewport, VideoViewport, WSIViewport, RenderingEngine, BaseRenderingEngine, TiledRenderingEngine, ContextPoolRenderingEngine, ImageVolume, Surface, getRenderingEngine, getRenderingEngines, getEnabledElement, getEnabledElementByIds, getEnabledElements, getEnabledElementByViewportId, createVolumeActor, createVolumeMapper, cache, eventTarget, triggerEvent, imageLoader, registerImageLoader, volumeLoader, metaData, utilities, setVolumesForViewports, addVolumesToViewports, addImageSlicesToViewports, imageLoadPoolManager as requestPoolManager, imageRetrievalPoolManager, imageLoadPoolManager, getShouldUseCPURendering, setUseCPURendering, setPreferSizeOverAccuracy, resetUseCPURendering, geometryLoader, cornerstoneMeshLoader, ProgressiveRetrieveImages, cornerstoneStreamingImageVolumeLoader, cornerstoneStreamingDynamicImageVolumeLoader, StreamingDynamicImageVolume, StreamingImageVolume, convertMapperToNotSharedMapper, version, };
|
|
42
|
+
export { init, isCornerstoneInitialized, peerImport, resetInitialization, getConfiguration, setConfiguration, getWebWorkerManager, canRenderFloatTextures, Enums, CONSTANTS, Events as EVENTS, Settings, BaseVolumeViewport, VolumeViewport, VolumeViewport3D, Viewport, StackViewport, VideoViewport, WSIViewport, RenderingEngine, BaseRenderingEngine, TiledRenderingEngine, ContextPoolRenderingEngine, ImageVolume, Surface, getRenderingEngine, getRenderingEngines, getEnabledElement, getEnabledElementByIds, getEnabledElements, getEnabledElementByViewportId, createVolumeActor, createVolumeMapper, cache, eventTarget, triggerEvent, imageLoader, registerImageLoader, volumeLoader, metaData, utilities, setVolumesForViewports, addVolumesToViewports, addImageSlicesToViewports, imageLoadPoolManager as requestPoolManager, imageRetrievalPoolManager, imageLoadPoolManager, getShouldUseCPURendering, setUseCPURendering, setPreferSizeOverAccuracy, resetUseCPURendering, geometryLoader, cornerstoneMeshLoader, ProgressiveRetrieveImages, decimatedVolumeLoader, cornerstoneStreamingImageVolumeLoader, cornerstoneStreamingDynamicImageVolumeLoader, StreamingDynamicImageVolume, StreamingImageVolume, convertMapperToNotSharedMapper, version, };
|
package/dist/esm/index.js
CHANGED
|
@@ -27,6 +27,7 @@ import * as volumeLoader from './loaders/volumeLoader';
|
|
|
27
27
|
import * as imageLoader from './loaders/imageLoader';
|
|
28
28
|
import * as geometryLoader from './loaders/geometryLoader';
|
|
29
29
|
import ProgressiveRetrieveImages from './loaders/ProgressiveRetrieveImages';
|
|
30
|
+
import { decimatedVolumeLoader } from './loaders/decimatedVolumeLoader';
|
|
30
31
|
import * as utilities from './utilities';
|
|
31
32
|
import { registerImageLoader } from './loaders/imageLoader';
|
|
32
33
|
import triggerEvent from './utilities/triggerEvent';
|
|
@@ -34,4 +35,5 @@ import { cornerstoneStreamingImageVolumeLoader } from './loaders/cornerstoneStre
|
|
|
34
35
|
import { cornerstoneStreamingDynamicImageVolumeLoader } from './loaders/cornerstoneStreamingDynamicImageVolumeLoader';
|
|
35
36
|
import { cornerstoneMeshLoader } from './loaders/cornerstoneMeshLoader';
|
|
36
37
|
import { setVolumesForViewports, addVolumesToViewports, addImageSlicesToViewports, } from './RenderingEngine/helpers';
|
|
37
|
-
export
|
|
38
|
+
export * from './loaders/decimatedVolumeLoader';
|
|
39
|
+
export { init, isCornerstoneInitialized, peerImport, resetInitialization, getConfiguration, setConfiguration, getWebWorkerManager, canRenderFloatTextures, Enums, CONSTANTS, Events as EVENTS, Settings, BaseVolumeViewport, VolumeViewport, VolumeViewport3D, Viewport, StackViewport, VideoViewport, WSIViewport, RenderingEngine, BaseRenderingEngine, TiledRenderingEngine, ContextPoolRenderingEngine, ImageVolume, Surface, getRenderingEngine, getRenderingEngines, getEnabledElement, getEnabledElementByIds, getEnabledElements, getEnabledElementByViewportId, createVolumeActor, createVolumeMapper, cache, eventTarget, triggerEvent, imageLoader, registerImageLoader, volumeLoader, metaData, utilities, setVolumesForViewports, addVolumesToViewports, addImageSlicesToViewports, imageLoadPoolManager as requestPoolManager, imageRetrievalPoolManager, imageLoadPoolManager, getShouldUseCPURendering, setUseCPURendering, setPreferSizeOverAccuracy, resetUseCPURendering, geometryLoader, cornerstoneMeshLoader, ProgressiveRetrieveImages, decimatedVolumeLoader, cornerstoneStreamingImageVolumeLoader, cornerstoneStreamingDynamicImageVolumeLoader, StreamingDynamicImageVolume, StreamingImageVolume, convertMapperToNotSharedMapper, version, };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import StreamingImageVolume from '../cache/classes/StreamingImageVolume';
|
|
2
|
+
import type { IRetrieveConfiguration } from '../types';
|
|
3
|
+
import type { points } from './decimatedVolumeModifiers';
|
|
4
|
+
interface IVolumeLoader {
|
|
5
|
+
promise: Promise<StreamingImageVolume>;
|
|
6
|
+
cancel: () => void;
|
|
7
|
+
decache: () => void;
|
|
8
|
+
}
|
|
9
|
+
export declare function decimatedVolumeLoader(volumeId: string, options: {
|
|
10
|
+
imageIds: string[];
|
|
11
|
+
progressiveRendering?: boolean | IRetrieveConfiguration;
|
|
12
|
+
ijkDecimation?: points.points3;
|
|
13
|
+
}): IVolumeLoader;
|
|
14
|
+
export default decimatedVolumeLoader;
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import StreamingImageVolume from '../cache/classes/StreamingImageVolume';
|
|
2
|
+
import { generateVolumePropsFromImageIds } from '../utilities/generateVolumePropsFromImageIds';
|
|
3
|
+
import decimate from '../utilities/decimate';
|
|
4
|
+
import VoxelManager from '../utilities/VoxelManager';
|
|
5
|
+
import { applyDecimatedVolumeModifiers, inPlaneDecimationModifier, } from './decimatedVolumeModifiers';
|
|
6
|
+
export function decimatedVolumeLoader(volumeId, options) {
|
|
7
|
+
if (!options || !options.imageIds || !options.imageIds.length) {
|
|
8
|
+
throw new Error('ImageIds must be provided to create a streaming image volume ');
|
|
9
|
+
}
|
|
10
|
+
const [iDecimation = 1, jDecimation = iDecimation, kDecimation = 1] = options.ijkDecimation ?? [];
|
|
11
|
+
const columnDecimation = Math.max(1, Math.floor(iDecimation));
|
|
12
|
+
const rowDecimation = jDecimation > 1 ? Math.max(1, Math.floor(jDecimation)) : columnDecimation;
|
|
13
|
+
const kAxisDecimation = Math.max(1, Math.floor(kDecimation));
|
|
14
|
+
const hasInPlaneDecimation = columnDecimation > 1 || rowDecimation > 1;
|
|
15
|
+
const modifierOptions = {
|
|
16
|
+
ijkDecimation: [
|
|
17
|
+
columnDecimation,
|
|
18
|
+
rowDecimation,
|
|
19
|
+
kAxisDecimation,
|
|
20
|
+
],
|
|
21
|
+
};
|
|
22
|
+
const modifiers = [inPlaneDecimationModifier];
|
|
23
|
+
function addDecimationToImageId(imageId, factor) {
|
|
24
|
+
if (factor === 1) {
|
|
25
|
+
return imageId;
|
|
26
|
+
}
|
|
27
|
+
return `${imageId}#decimation=${factor}`;
|
|
28
|
+
}
|
|
29
|
+
const expectedDecimatedCount = Math.floor(options.imageIds.length / kAxisDecimation);
|
|
30
|
+
const isAlreadyDecimated = kAxisDecimation > 1 &&
|
|
31
|
+
options.imageIds.length <= expectedDecimatedCount + 1;
|
|
32
|
+
if (kAxisDecimation > 1 && !isAlreadyDecimated) {
|
|
33
|
+
const decimatedResult = decimate(options.imageIds, kAxisDecimation);
|
|
34
|
+
const decimatedImageIds = Array.isArray(decimatedResult) &&
|
|
35
|
+
decimatedResult.length &&
|
|
36
|
+
typeof decimatedResult[0] === 'number'
|
|
37
|
+
? decimatedResult.map((idx) => options.imageIds[idx])
|
|
38
|
+
: decimatedResult;
|
|
39
|
+
options.imageIds = decimatedImageIds;
|
|
40
|
+
}
|
|
41
|
+
if (columnDecimation > 1) {
|
|
42
|
+
options.imageIds = options.imageIds.map((imageId) => addDecimationToImageId(imageId, columnDecimation));
|
|
43
|
+
}
|
|
44
|
+
async function getStreamingImageVolume() {
|
|
45
|
+
const baseVolumeProps = generateVolumePropsFromImageIds(options.imageIds, volumeId);
|
|
46
|
+
const modifierContext = {
|
|
47
|
+
volumeId,
|
|
48
|
+
imageIds: options.imageIds,
|
|
49
|
+
options: modifierOptions,
|
|
50
|
+
};
|
|
51
|
+
const volumeProps = applyDecimatedVolumeModifiers(baseVolumeProps, modifiers, modifierContext);
|
|
52
|
+
const { dimensions, spacing, origin, direction, metadata, imageIds, dataType, numberOfComponents, } = volumeProps;
|
|
53
|
+
const streamingImageVolume = new StreamingImageVolume({
|
|
54
|
+
volumeId,
|
|
55
|
+
metadata,
|
|
56
|
+
dimensions,
|
|
57
|
+
spacing,
|
|
58
|
+
origin,
|
|
59
|
+
direction,
|
|
60
|
+
imageIds,
|
|
61
|
+
dataType,
|
|
62
|
+
numberOfComponents,
|
|
63
|
+
}, {
|
|
64
|
+
imageIds,
|
|
65
|
+
loadStatus: {
|
|
66
|
+
loaded: false,
|
|
67
|
+
loading: false,
|
|
68
|
+
cancelled: false,
|
|
69
|
+
cachedFrames: [],
|
|
70
|
+
callbacks: [],
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
if (hasInPlaneDecimation) {
|
|
74
|
+
const vtkImageData = streamingImageVolume.imageData;
|
|
75
|
+
if (vtkImageData) {
|
|
76
|
+
vtkImageData.setDimensions(streamingImageVolume.dimensions);
|
|
77
|
+
vtkImageData.setSpacing(streamingImageVolume.spacing);
|
|
78
|
+
vtkImageData.modified();
|
|
79
|
+
}
|
|
80
|
+
const newVoxelManager = VoxelManager.createImageVolumeVoxelManager({
|
|
81
|
+
dimensions: streamingImageVolume.dimensions,
|
|
82
|
+
imageIds: streamingImageVolume.imageIds,
|
|
83
|
+
numberOfComponents: numberOfComponents,
|
|
84
|
+
});
|
|
85
|
+
streamingImageVolume.voxelManager = newVoxelManager;
|
|
86
|
+
if (vtkImageData) {
|
|
87
|
+
vtkImageData.set({
|
|
88
|
+
voxelManager: newVoxelManager,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return streamingImageVolume;
|
|
93
|
+
}
|
|
94
|
+
const streamingImageVolumePromise = getStreamingImageVolume();
|
|
95
|
+
return {
|
|
96
|
+
promise: streamingImageVolumePromise,
|
|
97
|
+
decache: () => {
|
|
98
|
+
streamingImageVolumePromise.then((streamingImageVolume) => {
|
|
99
|
+
streamingImageVolume.destroy();
|
|
100
|
+
streamingImageVolume = null;
|
|
101
|
+
});
|
|
102
|
+
},
|
|
103
|
+
cancel: () => {
|
|
104
|
+
streamingImageVolumePromise.then((streamingImageVolume) => {
|
|
105
|
+
streamingImageVolume.cancelLoading();
|
|
106
|
+
});
|
|
107
|
+
},
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
export default decimatedVolumeLoader;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { ImageVolumeProps } from '../../types';
|
|
2
|
+
import type { DecimatedVolumeModifier, DecimatedVolumeModifierContext } from './types';
|
|
3
|
+
export declare function applyDecimatedVolumeModifiers(baseProps: ImageVolumeProps, modifiers: DecimatedVolumeModifier[], context: DecimatedVolumeModifierContext): ImageVolumeProps;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export const inPlaneDecimationModifier = {
|
|
2
|
+
name: 'InPlaneDecimationModifier',
|
|
3
|
+
apply(volumeProps, context) {
|
|
4
|
+
const [iDecimation = 1, jDecimation = iDecimation] = context.options.ijkDecimation ?? [];
|
|
5
|
+
const columnFactor = Math.max(1, Math.floor(iDecimation));
|
|
6
|
+
const rowFactor = Math.max(1, Math.floor(jDecimation));
|
|
7
|
+
if (columnFactor === 1 && rowFactor === 1) {
|
|
8
|
+
return volumeProps;
|
|
9
|
+
}
|
|
10
|
+
const [columns, rows] = volumeProps.dimensions;
|
|
11
|
+
const newColumns = Math.max(1, Math.floor(columns / columnFactor));
|
|
12
|
+
const newRows = Math.max(1, Math.floor(rows / rowFactor));
|
|
13
|
+
const newDimensions = [
|
|
14
|
+
newColumns,
|
|
15
|
+
newRows,
|
|
16
|
+
volumeProps.dimensions[2],
|
|
17
|
+
];
|
|
18
|
+
const newSpacing = [
|
|
19
|
+
volumeProps.spacing[0] * columnFactor,
|
|
20
|
+
volumeProps.spacing[1] * rowFactor,
|
|
21
|
+
volumeProps.spacing[2],
|
|
22
|
+
];
|
|
23
|
+
const metadata = {
|
|
24
|
+
...volumeProps.metadata,
|
|
25
|
+
Columns: newColumns,
|
|
26
|
+
Rows: newRows,
|
|
27
|
+
PixelSpacing: [newSpacing[1], newSpacing[0]],
|
|
28
|
+
};
|
|
29
|
+
return {
|
|
30
|
+
...volumeProps,
|
|
31
|
+
dimensions: newDimensions,
|
|
32
|
+
spacing: newSpacing,
|
|
33
|
+
metadata,
|
|
34
|
+
};
|
|
35
|
+
},
|
|
36
|
+
};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { applyDecimatedVolumeModifiers } from './applyDecimatedVolumeModifiers';
|
|
2
|
+
export { inPlaneDecimationModifier } from './inPlaneDecimationModifier';
|
|
3
|
+
export type { DecimatedVolumeLoaderOptions, DecimatedVolumeModifier, DecimatedVolumeModifierContext, } from './types';
|
|
4
|
+
export type { points } from './types';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ImageVolumeProps } from '../../types';
|
|
2
|
+
import type Point3 from '../../types/Point3';
|
|
3
|
+
export declare namespace points {
|
|
4
|
+
type points3 = Point3;
|
|
5
|
+
}
|
|
6
|
+
export interface DecimatedVolumeLoaderOptions {
|
|
7
|
+
ijkDecimation?: points.points3;
|
|
8
|
+
}
|
|
9
|
+
export interface DecimatedVolumeModifierContext {
|
|
10
|
+
volumeId: string;
|
|
11
|
+
imageIds: string[];
|
|
12
|
+
options: DecimatedVolumeLoaderOptions;
|
|
13
|
+
}
|
|
14
|
+
export interface DecimatedVolumeModifier {
|
|
15
|
+
name: string;
|
|
16
|
+
apply(volumeProps: ImageVolumeProps, context: DecimatedVolumeModifierContext): ImageVolumeProps;
|
|
17
|
+
}
|
|
File without changes
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { cornerstoneStreamingImageVolumeLoader } from './cornerstoneStreamingImageVolumeLoader';
|
|
2
2
|
import { cornerstoneStreamingDynamicImageVolumeLoader } from './cornerstoneStreamingDynamicImageVolumeLoader';
|
|
3
3
|
import { cornerstoneMeshLoader } from './cornerstoneMeshLoader';
|
|
4
|
+
import { decimatedVolumeLoader } from './decimatedVolumeLoader';
|
|
4
5
|
import * as geometryLoader from './geometryLoader';
|
|
5
6
|
import * as imageLoader from './imageLoader';
|
|
6
7
|
import * as volumeLoader from './volumeLoader';
|
|
7
|
-
export { cornerstoneStreamingImageVolumeLoader, cornerstoneStreamingDynamicImageVolumeLoader, cornerstoneMeshLoader, geometryLoader, imageLoader, volumeLoader, };
|
|
8
|
+
export { cornerstoneStreamingImageVolumeLoader, cornerstoneStreamingDynamicImageVolumeLoader, cornerstoneMeshLoader, decimatedVolumeLoader, geometryLoader, imageLoader, volumeLoader, };
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { cornerstoneStreamingImageVolumeLoader } from './cornerstoneStreamingImageVolumeLoader';
|
|
2
2
|
import { cornerstoneStreamingDynamicImageVolumeLoader } from './cornerstoneStreamingDynamicImageVolumeLoader';
|
|
3
3
|
import { cornerstoneMeshLoader } from './cornerstoneMeshLoader';
|
|
4
|
+
import { decimatedVolumeLoader } from './decimatedVolumeLoader';
|
|
4
5
|
import * as geometryLoader from './geometryLoader';
|
|
5
6
|
import * as imageLoader from './imageLoader';
|
|
6
7
|
import * as volumeLoader from './volumeLoader';
|
|
7
|
-
export { cornerstoneStreamingImageVolumeLoader, cornerstoneStreamingDynamicImageVolumeLoader, cornerstoneMeshLoader, geometryLoader, imageLoader, volumeLoader, };
|
|
8
|
+
export { cornerstoneStreamingImageVolumeLoader, cornerstoneStreamingDynamicImageVolumeLoader, cornerstoneMeshLoader, decimatedVolumeLoader, geometryLoader, imageLoader, volumeLoader, };
|
|
@@ -4,6 +4,7 @@ import type { Point3, Metadata, Mat3, IImageVolume, VolumeLoaderFn, PixelDataTyp
|
|
|
4
4
|
interface VolumeLoaderOptions {
|
|
5
5
|
imageIds: string[];
|
|
6
6
|
progressiveRendering?: boolean;
|
|
7
|
+
ijkDecimation?: [number, number, number];
|
|
7
8
|
}
|
|
8
9
|
interface DerivedVolumeOptions {
|
|
9
10
|
volumeId?: string;
|
|
@@ -82,7 +82,7 @@ import { buildMetadata } from './buildMetadata';
|
|
|
82
82
|
import getDynamicVolumeInfo from './getDynamicVolumeInfo';
|
|
83
83
|
import autoLoad from './autoLoad';
|
|
84
84
|
import scaleArray from './scaleArray';
|
|
85
|
-
import splitImageIdsBy4DTags from './splitImageIdsBy4DTags';
|
|
85
|
+
import splitImageIdsBy4DTags, { handleMultiframe4D, generateFrameImageId } from './splitImageIdsBy4DTags';
|
|
86
86
|
import { deepClone } from './deepClone';
|
|
87
87
|
import { jumpToSlice } from './jumpToSlice';
|
|
88
88
|
import scroll from './scroll';
|
|
@@ -97,4 +97,4 @@ import { asArray } from './asArray';
|
|
|
97
97
|
export { updatePlaneRestriction } from './updatePlaneRestriction';
|
|
98
98
|
declare const getViewportModality: (viewport: IViewport, volumeId?: string) => string;
|
|
99
99
|
export * from './isEqual';
|
|
100
|
-
export { FrameRange, eventListener, csUtils as invertRgbTransferFunction, createSigmoidRGBTransferFunction, getVoiFromSigmoidRGBTransferFunction, createLinearRGBTransferFunction, scaleRgbTransferFunction, triggerEvent, imageIdToURI, fnv1aHash, calibratedPixelSpacingMetadataProvider, clamp, uuidv4, getMinMax, getRuntimeId, isOpposite, getViewportModality, windowLevel, convertToGrayscale, getClosestImageId, getSpacingInNormalDirection, getTargetVolumeAndSpacingInNormalDir, getVolumeActorCorners, indexWithinDimensions, getVolumeViewportsContainingSameVolumes, getViewportsWithVolumeId, transformWorldToIndex, transformIndexToWorld, loadImageToCanvas, renderToCanvasCPU, renderToCanvasGPU, worldToImageCoords, imageToWorldCoords, getVolumeSliceRangeInfo, getVolumeViewportScrollInfo, getSliceRange, snapFocalPointToSlice, getImageSliceDataForVolumeViewport, isImageActor, isPTPrescaledWithSUV, actorIsA, getViewportsWithImageURI, getClosestStackImageIndexForPoint, getCurrentVolumeViewportSlice, calculateViewportsSpatialRegistration, spatialRegistrationMetadataProvider, getViewportImageCornersInWorld, hasNaNValues, applyPreset, deepMerge, PointsManager, getScalingParameters, colormap, getImageLegacy, ProgressiveIterator, decimate, imageRetrieveMetadataProvider, transferFunctionUtils, updateVTKImageDataWithCornerstoneImage, sortImageIdsAndGetSpacing, makeVolumeMetadata, isValidVolume, genericMetadataProvider, isVideoTransferSyntax, HistoryMemo, generateVolumePropsFromImageIds, getBufferConfiguration, VoxelManager, RLEVoxelMap, convertStackToVolumeViewport, convertVolumeToStackViewport, roundNumber, roundToPrecision, getViewportImageIds, getRandomSampleFromArray, getVolumeId, color, hasFloatScalingParameters, getDynamicVolumeInfo, autoLoad, scaleArray, deepClone, splitImageIdsBy4DTags, pointInShapeCallback, deepEqual, jumpToSlice, scroll, clip, transformWorldToIndexContinuous, createSubVolume, getVolumeDirectionVectors, calculateSpacingBetweenImageIds, getImageDataMetadata, buildMetadata, calculateNeighborhoodStats, asArray, };
|
|
100
|
+
export { FrameRange, eventListener, csUtils as invertRgbTransferFunction, createSigmoidRGBTransferFunction, getVoiFromSigmoidRGBTransferFunction, createLinearRGBTransferFunction, scaleRgbTransferFunction, triggerEvent, imageIdToURI, fnv1aHash, calibratedPixelSpacingMetadataProvider, clamp, uuidv4, getMinMax, getRuntimeId, isOpposite, getViewportModality, windowLevel, convertToGrayscale, getClosestImageId, getSpacingInNormalDirection, getTargetVolumeAndSpacingInNormalDir, getVolumeActorCorners, indexWithinDimensions, getVolumeViewportsContainingSameVolumes, getViewportsWithVolumeId, transformWorldToIndex, transformIndexToWorld, loadImageToCanvas, renderToCanvasCPU, renderToCanvasGPU, worldToImageCoords, imageToWorldCoords, getVolumeSliceRangeInfo, getVolumeViewportScrollInfo, getSliceRange, snapFocalPointToSlice, getImageSliceDataForVolumeViewport, isImageActor, isPTPrescaledWithSUV, actorIsA, getViewportsWithImageURI, getClosestStackImageIndexForPoint, getCurrentVolumeViewportSlice, calculateViewportsSpatialRegistration, spatialRegistrationMetadataProvider, getViewportImageCornersInWorld, hasNaNValues, applyPreset, deepMerge, PointsManager, getScalingParameters, colormap, getImageLegacy, ProgressiveIterator, decimate, imageRetrieveMetadataProvider, transferFunctionUtils, updateVTKImageDataWithCornerstoneImage, sortImageIdsAndGetSpacing, makeVolumeMetadata, isValidVolume, genericMetadataProvider, isVideoTransferSyntax, HistoryMemo, generateVolumePropsFromImageIds, getBufferConfiguration, VoxelManager, RLEVoxelMap, convertStackToVolumeViewport, convertVolumeToStackViewport, roundNumber, roundToPrecision, getViewportImageIds, getRandomSampleFromArray, getVolumeId, color, hasFloatScalingParameters, getDynamicVolumeInfo, autoLoad, scaleArray, deepClone, splitImageIdsBy4DTags, handleMultiframe4D, generateFrameImageId, pointInShapeCallback, deepEqual, jumpToSlice, scroll, clip, transformWorldToIndexContinuous, createSubVolume, getVolumeDirectionVectors, calculateSpacingBetweenImageIds, getImageDataMetadata, buildMetadata, calculateNeighborhoodStats, asArray, };
|
|
@@ -83,7 +83,7 @@ import cache from '../cache/cache';
|
|
|
83
83
|
import getDynamicVolumeInfo from './getDynamicVolumeInfo';
|
|
84
84
|
import autoLoad from './autoLoad';
|
|
85
85
|
import scaleArray from './scaleArray';
|
|
86
|
-
import splitImageIdsBy4DTags from './splitImageIdsBy4DTags';
|
|
86
|
+
import splitImageIdsBy4DTags, { handleMultiframe4D, generateFrameImageId, } from './splitImageIdsBy4DTags';
|
|
87
87
|
import { deepClone } from './deepClone';
|
|
88
88
|
import { jumpToSlice } from './jumpToSlice';
|
|
89
89
|
import scroll from './scroll';
|
|
@@ -98,4 +98,4 @@ import { asArray } from './asArray';
|
|
|
98
98
|
export { updatePlaneRestriction } from './updatePlaneRestriction';
|
|
99
99
|
const getViewportModality = (viewport, volumeId) => _getViewportModality(viewport, volumeId, cache.getVolume);
|
|
100
100
|
export * from './isEqual';
|
|
101
|
-
export { FrameRange, eventListener, csUtils as invertRgbTransferFunction, createSigmoidRGBTransferFunction, getVoiFromSigmoidRGBTransferFunction, createLinearRGBTransferFunction, scaleRgbTransferFunction, triggerEvent, imageIdToURI, fnv1aHash, calibratedPixelSpacingMetadataProvider, clamp, uuidv4, getMinMax, getRuntimeId, isOpposite, getViewportModality, windowLevel, convertToGrayscale, getClosestImageId, getSpacingInNormalDirection, getTargetVolumeAndSpacingInNormalDir, getVolumeActorCorners, indexWithinDimensions, getVolumeViewportsContainingSameVolumes, getViewportsWithVolumeId, transformWorldToIndex, transformIndexToWorld, loadImageToCanvas, renderToCanvasCPU, renderToCanvasGPU, worldToImageCoords, imageToWorldCoords, getVolumeSliceRangeInfo, getVolumeViewportScrollInfo, getSliceRange, snapFocalPointToSlice, getImageSliceDataForVolumeViewport, isImageActor, isPTPrescaledWithSUV, actorIsA, getViewportsWithImageURI, getClosestStackImageIndexForPoint, getCurrentVolumeViewportSlice, calculateViewportsSpatialRegistration, spatialRegistrationMetadataProvider, getViewportImageCornersInWorld, hasNaNValues, applyPreset, deepMerge, PointsManager, getScalingParameters, colormap, getImageLegacy, ProgressiveIterator, decimate, imageRetrieveMetadataProvider, transferFunctionUtils, updateVTKImageDataWithCornerstoneImage, sortImageIdsAndGetSpacing, makeVolumeMetadata, isValidVolume, genericMetadataProvider, isVideoTransferSyntax, HistoryMemo, generateVolumePropsFromImageIds, getBufferConfiguration, VoxelManager, RLEVoxelMap, convertStackToVolumeViewport, convertVolumeToStackViewport, roundNumber, roundToPrecision, getViewportImageIds, getRandomSampleFromArray, getVolumeId, color, hasFloatScalingParameters, getDynamicVolumeInfo, autoLoad, scaleArray, deepClone, splitImageIdsBy4DTags, pointInShapeCallback, deepEqual, jumpToSlice, scroll, clip, transformWorldToIndexContinuous, createSubVolume, getVolumeDirectionVectors, calculateSpacingBetweenImageIds, getImageDataMetadata, buildMetadata, calculateNeighborhoodStats, asArray, };
|
|
101
|
+
export { FrameRange, eventListener, csUtils as invertRgbTransferFunction, createSigmoidRGBTransferFunction, getVoiFromSigmoidRGBTransferFunction, createLinearRGBTransferFunction, scaleRgbTransferFunction, triggerEvent, imageIdToURI, fnv1aHash, calibratedPixelSpacingMetadataProvider, clamp, uuidv4, getMinMax, getRuntimeId, isOpposite, getViewportModality, windowLevel, convertToGrayscale, getClosestImageId, getSpacingInNormalDirection, getTargetVolumeAndSpacingInNormalDir, getVolumeActorCorners, indexWithinDimensions, getVolumeViewportsContainingSameVolumes, getViewportsWithVolumeId, transformWorldToIndex, transformIndexToWorld, loadImageToCanvas, renderToCanvasCPU, renderToCanvasGPU, worldToImageCoords, imageToWorldCoords, getVolumeSliceRangeInfo, getVolumeViewportScrollInfo, getSliceRange, snapFocalPointToSlice, getImageSliceDataForVolumeViewport, isImageActor, isPTPrescaledWithSUV, actorIsA, getViewportsWithImageURI, getClosestStackImageIndexForPoint, getCurrentVolumeViewportSlice, calculateViewportsSpatialRegistration, spatialRegistrationMetadataProvider, getViewportImageCornersInWorld, hasNaNValues, applyPreset, deepMerge, PointsManager, getScalingParameters, colormap, getImageLegacy, ProgressiveIterator, decimate, imageRetrieveMetadataProvider, transferFunctionUtils, updateVTKImageDataWithCornerstoneImage, sortImageIdsAndGetSpacing, makeVolumeMetadata, isValidVolume, genericMetadataProvider, isVideoTransferSyntax, HistoryMemo, generateVolumePropsFromImageIds, getBufferConfiguration, VoxelManager, RLEVoxelMap, convertStackToVolumeViewport, convertVolumeToStackViewport, roundNumber, roundToPrecision, getViewportImageIds, getRandomSampleFromArray, getVolumeId, color, hasFloatScalingParameters, getDynamicVolumeInfo, autoLoad, scaleArray, deepClone, splitImageIdsBy4DTags, handleMultiframe4D, generateFrameImageId, pointInShapeCallback, deepEqual, jumpToSlice, scroll, clip, transformWorldToIndexContinuous, createSubVolume, getVolumeDirectionVectors, calculateSpacingBetweenImageIds, getImageDataMetadata, buildMetadata, calculateNeighborhoodStats, asArray, };
|
|
@@ -1,5 +1,12 @@
|
|
|
1
|
+
interface MultiframeSplitResult {
|
|
2
|
+
imageIdGroups: string[][];
|
|
3
|
+
splittingTag: string;
|
|
4
|
+
}
|
|
5
|
+
declare function generateFrameImageId(baseImageId: string, frameNumber: number): string;
|
|
6
|
+
declare function handleMultiframe4D(imageIds: string[]): MultiframeSplitResult | null;
|
|
1
7
|
declare function splitImageIdsBy4DTags(imageIds: string[]): {
|
|
2
8
|
imageIdGroups: string[][];
|
|
3
9
|
splittingTag: string | null;
|
|
4
10
|
};
|
|
5
11
|
export default splitImageIdsBy4DTags;
|
|
12
|
+
export { handleMultiframe4D, generateFrameImageId };
|
|
@@ -1,4 +1,72 @@
|
|
|
1
1
|
import * as metaData from '../metaData';
|
|
2
|
+
function generateFrameImageId(baseImageId, frameNumber) {
|
|
3
|
+
const framePattern = /\/frames\/\d+/;
|
|
4
|
+
if (!framePattern.test(baseImageId)) {
|
|
5
|
+
throw new Error(`generateFrameImageId: baseImageId must contain a "/frames/" pattern followed by a digit. ` +
|
|
6
|
+
`Expected format: e.g., "wadouri:http://example.com/image/frames/1" or "wadors:/path/to/image.dcm/frames/1". ` +
|
|
7
|
+
`Received: ${baseImageId}`);
|
|
8
|
+
}
|
|
9
|
+
return baseImageId.replace(framePattern, `/frames/${frameNumber}`);
|
|
10
|
+
}
|
|
11
|
+
function handleMultiframe4D(imageIds) {
|
|
12
|
+
if (!imageIds || imageIds.length === 0) {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
const baseImageId = imageIds[0];
|
|
16
|
+
const instance = metaData.get('instance', baseImageId);
|
|
17
|
+
if (!instance) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
const numberOfFrames = instance.NumberOfFrames;
|
|
21
|
+
if (!numberOfFrames || numberOfFrames <= 1) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
const timeSlotVector = instance.TimeSlotVector;
|
|
25
|
+
if (!timeSlotVector || !Array.isArray(timeSlotVector)) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
const sliceVector = instance.SliceVector;
|
|
29
|
+
const numberOfSlices = instance.NumberOfSlices;
|
|
30
|
+
if (timeSlotVector.length !== numberOfFrames) {
|
|
31
|
+
console.warn('TimeSlotVector length does not match NumberOfFrames:', timeSlotVector.length, 'vs', numberOfFrames);
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
if (sliceVector) {
|
|
35
|
+
if (!Array.isArray(sliceVector)) {
|
|
36
|
+
console.warn('SliceVector exists but is not an array. Expected length:', numberOfFrames);
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
if (sliceVector.length !== numberOfFrames ||
|
|
40
|
+
sliceVector.some((val) => val === undefined)) {
|
|
41
|
+
console.warn('SliceVector exists but has invalid length or undefined entries. Expected length:', numberOfFrames, 'Actual length:', sliceVector.length);
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
const timeSlotGroups = new Map();
|
|
46
|
+
for (let frameIndex = 0; frameIndex < numberOfFrames; frameIndex++) {
|
|
47
|
+
const timeSlot = timeSlotVector[frameIndex];
|
|
48
|
+
const sliceIndex = sliceVector?.[frameIndex] ?? frameIndex;
|
|
49
|
+
if (!timeSlotGroups.has(timeSlot)) {
|
|
50
|
+
timeSlotGroups.set(timeSlot, []);
|
|
51
|
+
}
|
|
52
|
+
timeSlotGroups.get(timeSlot).push({ frameIndex, sliceIndex });
|
|
53
|
+
}
|
|
54
|
+
const sortedTimeSlots = Array.from(timeSlotGroups.keys()).sort((a, b) => a - b);
|
|
55
|
+
const imageIdGroups = sortedTimeSlots.map((timeSlot) => {
|
|
56
|
+
const frames = timeSlotGroups.get(timeSlot);
|
|
57
|
+
frames.sort((a, b) => a.sliceIndex - b.sliceIndex);
|
|
58
|
+
return frames.map((frame) => generateFrameImageId(baseImageId, frame.frameIndex + 1));
|
|
59
|
+
});
|
|
60
|
+
const expectedSlicesPerTimeSlot = numberOfSlices || imageIdGroups[0]?.length;
|
|
61
|
+
const allGroupsHaveSameLength = imageIdGroups.every((group) => group.length === expectedSlicesPerTimeSlot);
|
|
62
|
+
if (!allGroupsHaveSameLength) {
|
|
63
|
+
console.warn('Multiframe 4D split resulted in uneven time slot groups. Expected', expectedSlicesPerTimeSlot, 'slices per time slot.');
|
|
64
|
+
}
|
|
65
|
+
return {
|
|
66
|
+
imageIdGroups,
|
|
67
|
+
splittingTag: 'TimeSlotVector',
|
|
68
|
+
};
|
|
69
|
+
}
|
|
2
70
|
const groupBy = (array, key) => {
|
|
3
71
|
return array.reduce((rv, x) => {
|
|
4
72
|
(rv[x[key]] = rv[x[key]] || []).push(x);
|
|
@@ -120,6 +188,10 @@ function getPetFrameReferenceTime(imageId) {
|
|
|
120
188
|
return moduleInfo ? moduleInfo['frameReferenceTime'] : 0;
|
|
121
189
|
}
|
|
122
190
|
function splitImageIdsBy4DTags(imageIds) {
|
|
191
|
+
const multiframeResult = handleMultiframe4D(imageIds);
|
|
192
|
+
if (multiframeResult) {
|
|
193
|
+
return multiframeResult;
|
|
194
|
+
}
|
|
123
195
|
const positionGroups = getIPPGroups(imageIds);
|
|
124
196
|
if (!positionGroups) {
|
|
125
197
|
return { imageIdGroups: [imageIds], splittingTag: null };
|
|
@@ -159,3 +231,4 @@ function splitImageIdsBy4DTags(imageIds) {
|
|
|
159
231
|
return { imageIdGroups: [imageIds], splittingTag: null };
|
|
160
232
|
}
|
|
161
233
|
export default splitImageIdsBy4DTags;
|
|
234
|
+
export { handleMultiframe4D, generateFrameImageId };
|
package/dist/esm/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const version = "4.
|
|
1
|
+
export declare const version = "4.15.1";
|
package/dist/esm/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = '4.
|
|
1
|
+
export const version = '4.15.1';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cornerstonejs/core",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.15.1",
|
|
4
4
|
"description": "Cornerstone3D Core",
|
|
5
5
|
"module": "./dist/esm/index.js",
|
|
6
6
|
"types": "./dist/esm/index.d.ts",
|
|
@@ -97,5 +97,5 @@
|
|
|
97
97
|
"type": "individual",
|
|
98
98
|
"url": "https://ohif.org/donate"
|
|
99
99
|
},
|
|
100
|
-
"gitHead": "
|
|
100
|
+
"gitHead": "4a9e19c7d7a8d5a6be2c906a1e887577880a2b93"
|
|
101
101
|
}
|