@cornerstonejs/core 1.42.0 → 1.43.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.
Files changed (199) hide show
  1. package/dist/cjs/RenderingEngine/BaseVolumeViewport.js +3 -0
  2. package/dist/cjs/RenderingEngine/BaseVolumeViewport.js.map +1 -1
  3. package/dist/cjs/RenderingEngine/StackViewport.js +2 -1
  4. package/dist/cjs/RenderingEngine/StackViewport.js.map +1 -1
  5. package/dist/cjs/RenderingEngine/Viewport.d.ts +1 -0
  6. package/dist/cjs/RenderingEngine/Viewport.js +3 -0
  7. package/dist/cjs/RenderingEngine/Viewport.js.map +1 -1
  8. package/dist/cjs/RenderingEngine/helpers/createVolumeActor.js +2 -1
  9. package/dist/cjs/RenderingEngine/helpers/createVolumeActor.js.map +1 -1
  10. package/dist/cjs/RenderingEngine/vtkClasses/vtkStreamingOpenGLVolumeMapper.js +1 -1
  11. package/dist/cjs/RenderingEngine/vtkClasses/vtkStreamingOpenGLVolumeMapper.js.map +1 -1
  12. package/dist/cjs/cache/cache.d.ts +6 -3
  13. package/dist/cjs/cache/cache.js +43 -6
  14. package/dist/cjs/cache/cache.js.map +1 -1
  15. package/dist/cjs/cache/classes/ImageVolume.d.ts +25 -5
  16. package/dist/cjs/cache/classes/ImageVolume.js +302 -13
  17. package/dist/cjs/cache/classes/ImageVolume.js.map +1 -1
  18. package/dist/cjs/eventTarget.d.ts +1 -0
  19. package/dist/cjs/eventTarget.js +13 -1
  20. package/dist/cjs/eventTarget.js.map +1 -1
  21. package/dist/cjs/init.js +2 -0
  22. package/dist/cjs/init.js.map +1 -1
  23. package/dist/cjs/loaders/imageLoader.d.ts +6 -1
  24. package/dist/cjs/loaders/imageLoader.js +26 -12
  25. package/dist/cjs/loaders/imageLoader.js.map +1 -1
  26. package/dist/cjs/loaders/volumeLoader.d.ts +13 -9
  27. package/dist/cjs/loaders/volumeLoader.js +58 -5
  28. package/dist/cjs/loaders/volumeLoader.js.map +1 -1
  29. package/dist/cjs/types/BoundsLPS.d.ts +3 -0
  30. package/dist/cjs/types/BoundsLPS.js +3 -0
  31. package/dist/cjs/types/BoundsLPS.js.map +1 -0
  32. package/dist/cjs/types/Cornerstone3DConfig.d.ts +1 -0
  33. package/dist/cjs/types/IDynamicImageVolume.d.ts +2 -2
  34. package/dist/cjs/types/IImage.d.ts +5 -0
  35. package/dist/cjs/types/IImageVolume.d.ts +7 -2
  36. package/dist/cjs/types/ILoadObject.d.ts +2 -2
  37. package/dist/cjs/types/IViewport.d.ts +1 -0
  38. package/dist/cjs/types/IVolume.d.ts +3 -26
  39. package/dist/cjs/types/ImageVolumeProps.d.ts +6 -0
  40. package/dist/cjs/types/ImageVolumeProps.js +3 -0
  41. package/dist/cjs/types/ImageVolumeProps.js.map +1 -0
  42. package/dist/cjs/types/VolumeProps.d.ts +27 -0
  43. package/dist/cjs/types/VolumeProps.js +3 -0
  44. package/dist/cjs/types/VolumeProps.js.map +1 -0
  45. package/dist/cjs/types/index.d.ts +5 -2
  46. package/dist/cjs/utilities/VoxelManager.d.ts +2 -2
  47. package/dist/cjs/utilities/VoxelManager.js +13 -4
  48. package/dist/cjs/utilities/VoxelManager.js.map +1 -1
  49. package/dist/cjs/utilities/cacheUtils.d.ts +2 -0
  50. package/dist/cjs/utilities/cacheUtils.js +96 -0
  51. package/dist/cjs/utilities/cacheUtils.js.map +1 -0
  52. package/dist/cjs/utilities/convertStackToVolumeViewport.d.ts +12 -0
  53. package/dist/cjs/utilities/convertStackToVolumeViewport.js +61 -0
  54. package/dist/cjs/utilities/convertStackToVolumeViewport.js.map +1 -0
  55. package/dist/cjs/utilities/convertVolumeToStackViewport.d.ts +9 -0
  56. package/dist/cjs/utilities/convertVolumeToStackViewport.js +95 -0
  57. package/dist/cjs/utilities/convertVolumeToStackViewport.js.map +1 -0
  58. package/dist/cjs/utilities/generateVolumePropsFromImageIds.d.ts +3 -0
  59. package/dist/cjs/utilities/generateVolumePropsFromImageIds.js +124 -0
  60. package/dist/cjs/utilities/generateVolumePropsFromImageIds.js.map +1 -0
  61. package/dist/cjs/utilities/index.d.ts +6 -1
  62. package/dist/cjs/utilities/index.js +12 -1
  63. package/dist/cjs/utilities/index.js.map +1 -1
  64. package/dist/cjs/utilities/planar.d.ts +1 -1
  65. package/dist/cjs/utilities/planar.js +5 -1
  66. package/dist/cjs/utilities/planar.js.map +1 -1
  67. package/dist/cjs/utilities/roundNumber.d.ts +4 -0
  68. package/dist/cjs/utilities/roundNumber.js +36 -0
  69. package/dist/cjs/utilities/roundNumber.js.map +1 -0
  70. package/dist/esm/RenderingEngine/BaseVolumeViewport.js +3 -0
  71. package/dist/esm/RenderingEngine/BaseVolumeViewport.js.map +1 -1
  72. package/dist/esm/RenderingEngine/StackViewport.js +2 -1
  73. package/dist/esm/RenderingEngine/StackViewport.js.map +1 -1
  74. package/dist/esm/RenderingEngine/Viewport.js +3 -0
  75. package/dist/esm/RenderingEngine/Viewport.js.map +1 -1
  76. package/dist/esm/RenderingEngine/helpers/createVolumeActor.js +1 -1
  77. package/dist/esm/RenderingEngine/helpers/createVolumeActor.js.map +1 -1
  78. package/dist/esm/RenderingEngine/vtkClasses/vtkStreamingOpenGLVolumeMapper.js +1 -1
  79. package/dist/esm/RenderingEngine/vtkClasses/vtkStreamingOpenGLVolumeMapper.js.map +1 -1
  80. package/dist/esm/cache/cache.js +43 -6
  81. package/dist/esm/cache/cache.js.map +1 -1
  82. package/dist/esm/cache/classes/ImageVolume.js +279 -14
  83. package/dist/esm/cache/classes/ImageVolume.js.map +1 -1
  84. package/dist/esm/eventTarget.js +13 -1
  85. package/dist/esm/eventTarget.js.map +1 -1
  86. package/dist/esm/init.js +2 -0
  87. package/dist/esm/init.js.map +1 -1
  88. package/dist/esm/loaders/imageLoader.js +23 -9
  89. package/dist/esm/loaders/imageLoader.js.map +1 -1
  90. package/dist/esm/loaders/volumeLoader.js +58 -5
  91. package/dist/esm/loaders/volumeLoader.js.map +1 -1
  92. package/dist/esm/types/BoundsLPS.js +2 -0
  93. package/dist/esm/types/BoundsLPS.js.map +1 -0
  94. package/dist/esm/types/ImageVolumeProps.js +2 -0
  95. package/dist/esm/types/ImageVolumeProps.js.map +1 -0
  96. package/dist/esm/types/VolumeProps.js +2 -0
  97. package/dist/esm/types/VolumeProps.js.map +1 -0
  98. package/dist/esm/utilities/VoxelManager.js +13 -4
  99. package/dist/esm/utilities/VoxelManager.js.map +1 -1
  100. package/dist/esm/utilities/cacheUtils.js +65 -0
  101. package/dist/esm/utilities/cacheUtils.js.map +1 -0
  102. package/dist/esm/utilities/convertStackToVolumeViewport.js +49 -0
  103. package/dist/esm/utilities/convertStackToVolumeViewport.js.map +1 -0
  104. package/dist/esm/utilities/convertVolumeToStackViewport.js +58 -0
  105. package/dist/esm/utilities/convertVolumeToStackViewport.js.map +1 -0
  106. package/dist/esm/utilities/generateVolumePropsFromImageIds.js +118 -0
  107. package/dist/esm/utilities/generateVolumePropsFromImageIds.js.map +1 -0
  108. package/dist/esm/utilities/index.js +6 -1
  109. package/dist/esm/utilities/index.js.map +1 -1
  110. package/dist/esm/utilities/planar.js +5 -1
  111. package/dist/esm/utilities/planar.js.map +1 -1
  112. package/dist/esm/utilities/roundNumber.js +33 -0
  113. package/dist/esm/utilities/roundNumber.js.map +1 -0
  114. package/dist/types/RenderingEngine/BaseVolumeViewport.d.ts.map +1 -1
  115. package/dist/types/RenderingEngine/StackViewport.d.ts.map +1 -1
  116. package/dist/types/RenderingEngine/Viewport.d.ts +1 -0
  117. package/dist/types/RenderingEngine/Viewport.d.ts.map +1 -1
  118. package/dist/types/RenderingEngine/vtkClasses/vtkStreamingOpenGLVolumeMapper.d.ts.map +1 -1
  119. package/dist/types/cache/cache.d.ts +6 -3
  120. package/dist/types/cache/cache.d.ts.map +1 -1
  121. package/dist/types/cache/classes/ImageVolume.d.ts +25 -5
  122. package/dist/types/cache/classes/ImageVolume.d.ts.map +1 -1
  123. package/dist/types/eventTarget.d.ts +1 -0
  124. package/dist/types/eventTarget.d.ts.map +1 -1
  125. package/dist/types/loaders/imageLoader.d.ts +6 -1
  126. package/dist/types/loaders/imageLoader.d.ts.map +1 -1
  127. package/dist/types/loaders/volumeLoader.d.ts +13 -9
  128. package/dist/types/loaders/volumeLoader.d.ts.map +1 -1
  129. package/dist/types/types/BoundsLPS.d.ts +4 -0
  130. package/dist/types/types/BoundsLPS.d.ts.map +1 -0
  131. package/dist/types/types/Cornerstone3DConfig.d.ts +1 -0
  132. package/dist/types/types/Cornerstone3DConfig.d.ts.map +1 -1
  133. package/dist/types/types/IDynamicImageVolume.d.ts +2 -2
  134. package/dist/types/types/IDynamicImageVolume.d.ts.map +1 -1
  135. package/dist/types/types/IImage.d.ts +5 -0
  136. package/dist/types/types/IImage.d.ts.map +1 -1
  137. package/dist/types/types/IImageVolume.d.ts +7 -2
  138. package/dist/types/types/IImageVolume.d.ts.map +1 -1
  139. package/dist/types/types/ILoadObject.d.ts +2 -2
  140. package/dist/types/types/ILoadObject.d.ts.map +1 -1
  141. package/dist/types/types/IViewport.d.ts +1 -0
  142. package/dist/types/types/IViewport.d.ts.map +1 -1
  143. package/dist/types/types/IVolume.d.ts +3 -26
  144. package/dist/types/types/IVolume.d.ts.map +1 -1
  145. package/dist/types/types/ImageVolumeProps.d.ts +7 -0
  146. package/dist/types/types/ImageVolumeProps.d.ts.map +1 -0
  147. package/dist/types/types/VolumeProps.d.ts +28 -0
  148. package/dist/types/types/VolumeProps.d.ts.map +1 -0
  149. package/dist/types/types/index.d.ts +5 -2
  150. package/dist/types/types/index.d.ts.map +1 -1
  151. package/dist/types/utilities/VoxelManager.d.ts +2 -2
  152. package/dist/types/utilities/VoxelManager.d.ts.map +1 -1
  153. package/dist/types/utilities/cacheUtils.d.ts +3 -0
  154. package/dist/types/utilities/cacheUtils.d.ts.map +1 -0
  155. package/dist/types/utilities/convertStackToVolumeViewport.d.ts +13 -0
  156. package/dist/types/utilities/convertStackToVolumeViewport.d.ts.map +1 -0
  157. package/dist/types/utilities/convertVolumeToStackViewport.d.ts +10 -0
  158. package/dist/types/utilities/convertVolumeToStackViewport.d.ts.map +1 -0
  159. package/dist/types/utilities/generateVolumePropsFromImageIds.d.ts +4 -0
  160. package/dist/types/utilities/generateVolumePropsFromImageIds.d.ts.map +1 -0
  161. package/dist/types/utilities/index.d.ts +6 -1
  162. package/dist/types/utilities/index.d.ts.map +1 -1
  163. package/dist/types/utilities/planar.d.ts +1 -1
  164. package/dist/types/utilities/planar.d.ts.map +1 -1
  165. package/dist/types/utilities/roundNumber.d.ts +5 -0
  166. package/dist/types/utilities/roundNumber.d.ts.map +1 -0
  167. package/dist/umd/index.js +1 -1
  168. package/dist/umd/index.js.map +1 -1
  169. package/package.json +3 -3
  170. package/src/RenderingEngine/BaseVolumeViewport.ts +4 -1
  171. package/src/RenderingEngine/StackViewport.ts +3 -1
  172. package/src/RenderingEngine/Viewport.ts +9 -1
  173. package/src/RenderingEngine/helpers/createVolumeActor.ts +1 -1
  174. package/src/RenderingEngine/vtkClasses/vtkStreamingOpenGLVolumeMapper.js +3 -26
  175. package/src/cache/cache.ts +91 -7
  176. package/src/cache/classes/ImageVolume.ts +535 -21
  177. package/src/eventTarget.ts +19 -1
  178. package/src/init.ts +2 -2
  179. package/src/loaders/imageLoader.ts +58 -10
  180. package/src/loaders/volumeLoader.ts +139 -23
  181. package/src/types/BoundsLPS.ts +5 -0
  182. package/src/types/Cornerstone3DConfig.ts +12 -0
  183. package/src/types/IDynamicImageVolume.ts +2 -2
  184. package/src/types/IImage.ts +6 -0
  185. package/src/types/IImageVolume.ts +14 -2
  186. package/src/types/ILoadObject.ts +2 -2
  187. package/src/types/IViewport.ts +2 -1
  188. package/src/types/IVolume.ts +4 -41
  189. package/src/types/ImageVolumeProps.ts +15 -0
  190. package/src/types/VolumeProps.ts +57 -0
  191. package/src/types/index.ts +7 -2
  192. package/src/utilities/VoxelManager.ts +17 -6
  193. package/src/utilities/cacheUtils.ts +121 -0
  194. package/src/utilities/convertStackToVolumeViewport.ts +115 -0
  195. package/src/utilities/convertVolumeToStackViewport.ts +125 -0
  196. package/src/utilities/generateVolumePropsFromImageIds.ts +183 -0
  197. package/src/utilities/index.ts +11 -0
  198. package/src/utilities/planar.ts +12 -1
  199. package/src/utilities/roundNumber.ts +56 -0
@@ -1,4 +1,5 @@
1
1
  import cache from '../cache/cache';
2
+ import { ImageVolume } from '../cache';
2
3
  import Events from '../enums/Events';
3
4
  import eventTarget from '../eventTarget';
4
5
  import {
@@ -120,11 +121,14 @@ function loadImageFromCacheOrVolume(
120
121
  // 2. Check if there exists a volume in the cache containing the imageId,
121
122
  // we copy the pixelData over.
122
123
  const cachedVolumeInfo = cache.getVolumeContainingImageId(imageId);
123
- if (cachedVolumeInfo && cachedVolumeInfo.volume.loadStatus.loaded) {
124
+ if (cachedVolumeInfo?.volume?.loadStatus?.loaded) {
124
125
  // 2.1 Convert the volume at the specific slice to a cornerstoneImage object.
125
126
  // this will copy the pixel data over.
126
127
  const { volume, imageIdIndex } = cachedVolumeInfo;
127
- imageLoadObject = volume.convertToCornerstoneImage(imageId, imageIdIndex);
128
+
129
+ if (volume instanceof ImageVolume) {
130
+ imageLoadObject = volume.convertToCornerstoneImage(imageId, imageIdIndex);
131
+ }
128
132
  return imageLoadObject;
129
133
  }
130
134
  // 3. If no volume found, we search inside the imageCache for the imageId
@@ -285,11 +289,16 @@ export function createAndCacheDerivedImage(
285
289
  * Load and cache a list of imageIds
286
290
  *
287
291
  * @param referencedImageIds - list of imageIds
288
- * @param getDerivedImageId - optional function to generate derived imageId name however you want
292
+ * @param options
293
+ * @param options.getDerivedImageId - function to get the derived imageId
294
+ * @param options.targetBufferType - target buffer type
289
295
  */
290
296
  export function createAndCacheDerivedImages(
291
297
  referencedImageIds: Array<string>,
292
- getDerivedImageId?: (referencedImageId: string) => string
298
+ options: {
299
+ getDerivedImageId?: (referencedImageId: string) => string;
300
+ targetBufferType?: PixelDataTypedArrayString;
301
+ } = {}
293
302
  ): DerivedImages {
294
303
  if (referencedImageIds?.length === 0) {
295
304
  throw new Error(
@@ -298,14 +307,15 @@ export function createAndCacheDerivedImages(
298
307
  }
299
308
 
300
309
  const derivedImageIds = [];
301
- const allPromises = referencedImageIds.map((referencedImageId, index) => {
302
- const options: DerivedImageOptions = {
303
- imageId: getDerivedImageId
304
- ? getDerivedImageId(referencedImageId)
310
+ const allPromises = referencedImageIds.map((referencedImageId) => {
311
+ const newOptions: DerivedImageOptions = {
312
+ imageId: options.getDerivedImageId
313
+ ? options.getDerivedImageId(referencedImageId)
305
314
  : `derived:${uuidv4()}`,
315
+ ...options,
306
316
  };
307
- derivedImageIds.push(options.imageId);
308
- return createAndCacheDerivedImage(referencedImageId, options);
317
+ derivedImageIds.push(newOptions.imageId);
318
+ return createAndCacheDerivedImage(referencedImageId, newOptions);
309
319
  });
310
320
 
311
321
  return { imageIds: derivedImageIds, promises: allPromises };
@@ -497,3 +507,41 @@ export function unregisterAllImageLoaders(): void {
497
507
  );
498
508
  unknownImageLoader = undefined;
499
509
  }
510
+
511
+ /**
512
+ * Creates and caches derived segmentation images based on the referenced imageIds, this
513
+ * is a helper function, we don't have segmentation concept in the cornerstone core; however,
514
+ * this helper would make it clear that the segmentation images SHOULD be Uint8Array type
515
+ * always until we have a better solution.
516
+ *
517
+ * @param referencedImageIds - An array of referenced image IDs.
518
+ * @param options - The options for creating the derived images (default: { targetBufferType: 'Uint8Array' }).
519
+ * @returns The derived images.
520
+ */
521
+ export function createAndCacheDerivedSegmentationImages(
522
+ referencedImageIds: Array<string>,
523
+ options: DerivedImageOptions = {
524
+ targetBufferType: 'Uint8Array',
525
+ }
526
+ ): DerivedImages {
527
+ return createAndCacheDerivedImages(referencedImageIds, options);
528
+ }
529
+
530
+ /**
531
+ * Creates and caches a derived segmentation image based on the referenced image ID.
532
+ * this is a helper function, we don't have segmentation concept in the cornerstone core; however,
533
+ * this helper would make it clear that the segmentation images SHOULD be Uint8Array type
534
+ * always until we have a better solution.
535
+ *
536
+ * @param referencedImageId The ID of the referenced image.
537
+ * @param options The options for creating the derived image (default: { targetBufferType: 'Uint8Array' }).
538
+ * @returns A promise that resolves to the created derived segmentation image.
539
+ */
540
+ export function createAndCacheDerivedSegmentationImage(
541
+ referencedImageId: string,
542
+ options: DerivedImageOptions = {
543
+ targetBufferType: 'Uint8Array',
544
+ }
545
+ ): Promise<IImage> {
546
+ return createAndCacheDerivedImage(referencedImageId, options);
547
+ }
@@ -6,20 +6,32 @@ import vtkDataArray from '@kitware/vtk.js/Common/Core/DataArray';
6
6
  import cloneDeep from 'lodash.clonedeep';
7
7
 
8
8
  import { ImageVolume } from '../cache/classes/ImageVolume';
9
- import type * as Types from '../types';
10
9
  import cache from '../cache/cache';
11
10
  import Events from '../enums/Events';
12
11
  import eventTarget from '../eventTarget';
13
12
  import triggerEvent from '../utilities/triggerEvent';
14
- import { getBufferConfiguration, uuidv4 } from '../utilities';
13
+ import {
14
+ generateVolumePropsFromImageIds,
15
+ getBufferConfiguration,
16
+ uuidv4,
17
+ } from '../utilities';
15
18
  import {
16
19
  Point3,
17
20
  Metadata,
18
21
  EventTypes,
19
22
  Mat3,
23
+ IImageVolume,
24
+ VolumeLoaderFn,
25
+ IDynamicImageVolume,
20
26
  PixelDataTypedArray,
27
+ IVolumeLoadObject,
28
+ PixelDataTypedArrayString,
21
29
  } from '../types';
22
30
  import { getConfiguration } from '../init';
31
+ import {
32
+ performCacheOptimizationForVolume,
33
+ setupCacheOptimizationEventListener,
34
+ } from '../utilities/cacheUtils';
23
35
 
24
36
  interface VolumeLoaderOptions {
25
37
  imageIds: Array<string>;
@@ -28,7 +40,7 @@ interface VolumeLoaderOptions {
28
40
  interface DerivedVolumeOptions {
29
41
  volumeId: string;
30
42
  targetBuffer?: {
31
- type: 'Float32Array' | 'Uint8Array' | 'Uint16Array' | 'Int16Array';
43
+ type: PixelDataTypedArrayString;
32
44
  sharedArrayBuffer?: boolean;
33
45
  };
34
46
  }
@@ -46,7 +58,7 @@ interface LocalVolumeOptions {
46
58
  */
47
59
  function addScalarDataToImageData(
48
60
  imageData: vtkImageDataType,
49
- scalarData: Types.VolumeScalarData,
61
+ scalarData: PixelDataTypedArray,
50
62
  dataArrayAttrs
51
63
  ) {
52
64
  const scalarArray = vtkDataArray.newInstance({
@@ -63,7 +75,7 @@ function addScalarDataToImageData(
63
75
  */
64
76
  function addScalarDataArraysToImageData(
65
77
  imageData: vtkImageDataType,
66
- scalarDataArrays: Types.VolumeScalarData[],
78
+ scalarDataArrays: PixelDataTypedArray[],
67
79
  dataArrayAttrs
68
80
  ) {
69
81
  scalarDataArrays.forEach((scalarData, i) => {
@@ -81,7 +93,7 @@ function addScalarDataArraysToImageData(
81
93
  }
82
94
 
83
95
  function createInternalVTKRepresentation(
84
- volume: Types.IImageVolume
96
+ volume: IImageVolume
85
97
  ): vtkImageDataType {
86
98
  const { dimensions, metadata, spacing, direction, origin } = volume;
87
99
  const { PhotometricInterpretation } = metadata;
@@ -101,7 +113,7 @@ function createInternalVTKRepresentation(
101
113
 
102
114
  // Add scalar data to 3D or 4D volume
103
115
  if (volume.isDynamicVolume()) {
104
- const scalarDataArrays = (<Types.IDynamicImageVolume>(
116
+ const scalarDataArrays = (<IDynamicImageVolume>(
105
117
  volume
106
118
  )).getScalarDataArrays();
107
119
 
@@ -139,23 +151,28 @@ let unknownVolumeLoader;
139
151
  function loadVolumeFromVolumeLoader(
140
152
  volumeId: string,
141
153
  options?: VolumeLoaderOptions
142
- ): Types.IVolumeLoadObject {
154
+ ): IVolumeLoadObject {
143
155
  const colonIndex = volumeId.indexOf(':');
144
156
  const scheme = volumeId.substring(0, colonIndex);
145
- const loader = volumeLoaders[scheme];
157
+ let loader = volumeLoaders[scheme];
146
158
 
147
159
  if (loader === undefined || loader === null) {
148
- if (unknownVolumeLoader !== undefined) {
149
- return unknownVolumeLoader(volumeId, options);
160
+ if (
161
+ unknownVolumeLoader == null ||
162
+ typeof unknownVolumeLoader !== 'function'
163
+ ) {
164
+ throw new Error(
165
+ `No volume loader for scheme ${scheme} has been registered`
166
+ );
150
167
  }
151
168
 
152
- throw new Error(
153
- 'loadVolumeFromVolumeLoader: no volume loader for volumeId'
154
- );
169
+ loader = unknownVolumeLoader;
155
170
  }
156
171
 
157
172
  const volumeLoadObject = loader(volumeId, options);
158
173
 
174
+ setupCacheOptimizationEventListener(volumeId);
175
+
159
176
  // Broadcast a volume loaded event once the image is loaded
160
177
  volumeLoadObject.promise.then(
161
178
  function (volume) {
@@ -186,7 +203,7 @@ function loadVolumeFromVolumeLoader(
186
203
  export function loadVolume(
187
204
  volumeId: string,
188
205
  options: VolumeLoaderOptions = { imageIds: [] }
189
- ): Promise<Types.IImageVolume> {
206
+ ): Promise<IImageVolume> {
190
207
  if (volumeId === undefined) {
191
208
  throw new Error('loadVolume: parameter volumeId must not be undefined');
192
209
  }
@@ -199,7 +216,7 @@ export function loadVolume(
199
216
 
200
217
  volumeLoadObject = loadVolumeFromVolumeLoader(volumeId, options);
201
218
 
202
- return volumeLoadObject.promise.then((volume: Types.IImageVolume) => {
219
+ return volumeLoadObject.promise.then((volume: IImageVolume) => {
203
220
  volume.imageData = createInternalVTKRepresentation(volume);
204
221
  return volume;
205
222
  });
@@ -232,7 +249,7 @@ export async function createAndCacheVolume(
232
249
 
233
250
  volumeLoadObject = loadVolumeFromVolumeLoader(volumeId, options);
234
251
 
235
- volumeLoadObject.promise.then((volume: Types.IImageVolume) => {
252
+ volumeLoadObject.promise.then((volume: IImageVolume) => {
236
253
  volume.imageData = createInternalVTKRepresentation(volume);
237
254
  });
238
255
 
@@ -258,7 +275,7 @@ export async function createAndCacheVolume(
258
275
  export async function createAndCacheDerivedVolume(
259
276
  referencedVolumeId: string,
260
277
  options: DerivedVolumeOptions
261
- ): Promise<ImageVolume> {
278
+ ): Promise<IImageVolume> {
262
279
  const referencedVolume = cache.getVolume(referencedVolumeId);
263
280
 
264
281
  if (!referencedVolume) {
@@ -330,6 +347,7 @@ export async function createAndCacheDerivedVolume(
330
347
  scalarData: volumeScalarData,
331
348
  sizeInBytes: numBytes,
332
349
  referencedVolumeId,
350
+ imageIds: [],
333
351
  });
334
352
 
335
353
  const volumeLoadObject = {
@@ -355,7 +373,7 @@ export function createLocalVolume(
355
373
  options: LocalVolumeOptions,
356
374
  volumeId: string,
357
375
  preventCache = false
358
- ): ImageVolume {
376
+ ): IImageVolume {
359
377
  const { scalarData, metadata, dimensions, spacing, origin, direction } =
360
378
  options;
361
379
 
@@ -381,7 +399,7 @@ export function createLocalVolume(
381
399
  const cachedVolume = cache.getVolume(volumeId);
382
400
 
383
401
  if (cachedVolume) {
384
- return cachedVolume as ImageVolume;
402
+ return cachedVolume as IImageVolume;
385
403
  }
386
404
 
387
405
  const scalarLength = dimensions[0] * dimensions[1] * dimensions[2];
@@ -418,6 +436,7 @@ export function createLocalVolume(
418
436
  imageData: imageData,
419
437
  scalarData,
420
438
  sizeInBytes: numBytes,
439
+ imageIds: [],
421
440
  });
422
441
 
423
442
  if (preventCache) {
@@ -432,6 +451,78 @@ export function createLocalVolume(
432
451
  return derivedVolume;
433
452
  }
434
453
 
454
+ export async function createAndCacheVolumeFromImages(
455
+ volumeId: string,
456
+ imageIds: string[],
457
+ options: {
458
+ preventCache?: boolean;
459
+ additionalDetails?: Record<string, any>;
460
+ } = {}
461
+ ): Promise<IImageVolume> {
462
+ const { preventCache = false } = options;
463
+
464
+ if (imageIds === undefined) {
465
+ throw new Error(
466
+ 'createAndCacheVolumeFromImages: parameter imageIds must not be undefined'
467
+ );
468
+ }
469
+
470
+ if (volumeId === undefined) {
471
+ throw new Error(
472
+ 'createAndCacheVolumeFromImages: parameter volumeId must not be undefined'
473
+ );
474
+ }
475
+
476
+ const cachedVolume = cache.getVolume(volumeId);
477
+
478
+ if (cachedVolume) {
479
+ return Promise.resolve(cachedVolume);
480
+ }
481
+
482
+ const volumeProps = generateVolumePropsFromImageIds(imageIds, volumeId);
483
+
484
+ // volume is an empty volume, we need to load the data from the imageIds
485
+ // into the volume scalarData
486
+
487
+ // it is important to get the imageIds from the volumeProps
488
+ // since they are sorted
489
+ const imagePromises = volumeProps.imageIds.map((imageId, imageIdIndex) => {
490
+ const imageLoadObject = cache.getImageLoadObject(imageId);
491
+
492
+ return imageLoadObject.promise.then((image) => {
493
+ const pixelData = image.getPixelData();
494
+ const offset = imageIdIndex * image.rows * image.columns;
495
+
496
+ (volumeProps.scalarData as PixelDataTypedArray).set(pixelData, offset);
497
+ });
498
+ });
499
+
500
+ await Promise.all(imagePromises);
501
+
502
+ const volume = new ImageVolume({
503
+ ...volumeProps,
504
+ referencedImageIds: imageIds,
505
+ ...options,
506
+ });
507
+
508
+ // since we generated the volume from images, we can optimize the cache
509
+ // by replacing the pixelData of the images with a view of the volume's
510
+ // scalarData
511
+ performCacheOptimizationForVolume(volume);
512
+
513
+ const volumeLoadObject = {
514
+ promise: Promise.resolve(volume),
515
+ };
516
+
517
+ if (preventCache) {
518
+ return volumeLoadObject.promise;
519
+ }
520
+
521
+ cache.putVolumeLoadObject(volumeId, volumeLoadObject);
522
+
523
+ return volumeLoadObject.promise;
524
+ }
525
+
435
526
  /**
436
527
  * Registers an volumeLoader plugin with cornerstone for the specified scheme
437
528
  *
@@ -440,7 +531,7 @@ export function createLocalVolume(
440
531
  */
441
532
  export function registerVolumeLoader(
442
533
  scheme: string,
443
- volumeLoader: Types.VolumeLoaderFn
534
+ volumeLoader: VolumeLoaderFn
444
535
  ): void {
445
536
  volumeLoaders[scheme] = volumeLoader;
446
537
  }
@@ -458,11 +549,36 @@ export function getVolumeLoaderSchemes(): string[] {
458
549
  * @returns The previous Unknown Volume Loader
459
550
  */
460
551
  export function registerUnknownVolumeLoader(
461
- volumeLoader: Types.VolumeLoaderFn
462
- ): Types.VolumeLoaderFn | undefined {
552
+ volumeLoader: VolumeLoaderFn
553
+ ): VolumeLoaderFn | undefined {
463
554
  const oldVolumeLoader = unknownVolumeLoader;
464
555
 
465
556
  unknownVolumeLoader = volumeLoader;
466
557
 
467
558
  return oldVolumeLoader;
468
559
  }
560
+
561
+ export function getUnknownVolumeLoaderSchema(): string {
562
+ return unknownVolumeLoader.name;
563
+ }
564
+
565
+ /**
566
+ * Creates and caches a derived segmentation volume based on a referenced volume.
567
+ * This is basically a utility method since for the segmentations we have to specify
568
+ * Uint8Array as the targetBuffer type for now until we support other types.
569
+ *
570
+ * @param referencedVolumeId - The ID of the referenced volume.
571
+ * @param options - The options for creating the derived volume.
572
+ * @returns A promise that resolves to the created derived segmentation volume.
573
+ */
574
+ export async function createAndCacheDerivedSegmentationVolume(
575
+ referencedVolumeId: string,
576
+ options: DerivedVolumeOptions
577
+ ): Promise<IImageVolume> {
578
+ return createAndCacheDerivedVolume(referencedVolumeId, {
579
+ ...options,
580
+ targetBuffer: {
581
+ type: 'Uint8Array',
582
+ },
583
+ });
584
+ }
@@ -0,0 +1,5 @@
1
+ import type Point2 from './Point3';
2
+
3
+ type BoundsLPS = [Point2, Point2, Point2];
4
+
5
+ export default BoundsLPS;
@@ -51,6 +51,18 @@ type Cornerstone3DConfig = {
51
51
  */
52
52
  strictZSpacingForVolumeViewport: boolean;
53
53
  };
54
+ /**
55
+ * This flag controls whether to enable cache optimization or not. Basically,
56
+ * when we have a stack viewport (image stack) and we convert it to a volume
57
+ * the volume will be cached as well as the stack. However, if we can optimize this
58
+ * by going back to the image cache and create a view at the correct offset
59
+ * of the bigger volume array buffer, this will save memory. This will get enabled
60
+ * if cornerstone3D is configured to use SharedArrayBuffer, the reason is that
61
+ * when we modify the image cache then the images are referring to a different
62
+ * buffer (SharedArrayBuffer) and some systems don't support shared array
63
+ * buffers.
64
+ */
65
+ enableCacheOptimization: boolean;
54
66
  };
55
67
 
56
68
  export default Cornerstone3DConfig;
@@ -1,4 +1,4 @@
1
- import { IImageVolume, VolumeScalarData } from '../types';
1
+ import { IImageVolume, PixelDataTypedArray } from '../types';
2
2
 
3
3
  /**
4
4
  * Cornerstone ImageVolume interface. Todo: we should define new IVolume class
@@ -12,7 +12,7 @@ interface IDynamicImageVolume extends IImageVolume {
12
12
  /** Returns the number of time points */
13
13
  get numTimePoints(): number;
14
14
  /** return scalar data arrays (one per timepoint) */
15
- getScalarDataArrays(): VolumeScalarData[];
15
+ getScalarDataArrays(): PixelDataTypedArray[];
16
16
  }
17
17
 
18
18
  export default IDynamicImageVolume;
@@ -120,6 +120,12 @@ interface IImage {
120
120
 
121
121
  imageQualityStatus?: ImageQualityStatus;
122
122
  calibration?: IImageCalibration;
123
+ imageFrame?: any;
124
+
125
+ bufferView?: {
126
+ buffer: ArrayBuffer;
127
+ offset: number;
128
+ };
123
129
  }
124
130
 
125
131
  export default IImage;
@@ -1,7 +1,7 @@
1
1
  import type { vtkImageData } from '@kitware/vtk.js/Common/DataModel/ImageData';
2
2
  import {
3
3
  Metadata,
4
- VolumeScalarData,
4
+ PixelDataTypedArray,
5
5
  Point3,
6
6
  IImageLoadObject,
7
7
  Mat3,
@@ -49,8 +49,12 @@ interface IImageVolume {
49
49
  imageIds: Array<string>;
50
50
  /** volume referencedVolumeId (if it is derived from another volume) */
51
51
  referencedVolumeId?: string; // if volume is derived from another volume
52
+ /** volume referencedImageIds (if it is derived from set of images in the image cache) */
53
+ referencedImageIds?: Array<string>;
52
54
  /** whether the metadata for the pixel spacing is not undefined */
53
55
  hasPixelSpacing: boolean;
56
+ /** Property to store additional information */
57
+ additionalDetails?: Record<string, any>;
54
58
  /** return true if it is a 4D volume or false if it is 3D volume */
55
59
  isDynamicVolume(): boolean;
56
60
  /** method to convert the volume data in the volume cache, to separate images in the image cache */
@@ -63,7 +67,9 @@ interface IImageVolume {
63
67
  cancelLoading?: () => void;
64
68
 
65
69
  /** return the volume scalar data */
66
- getScalarData(): VolumeScalarData;
70
+ getScalarData(): PixelDataTypedArray;
71
+
72
+ convertToImageSlicesAndCache(): string[];
67
73
 
68
74
  /** return the index of a given imageId */
69
75
  getImageIdIndex(imageId: string): number;
@@ -73,6 +79,12 @@ interface IImageVolume {
73
79
 
74
80
  /** destroy the volume and make it unusable */
75
81
  destroy(): void;
82
+
83
+ /** decache */
84
+ decache?: () => void;
85
+
86
+ /** */
87
+ get imageCacheOffsetMap(): Map<string, any>;
76
88
  }
77
89
 
78
90
  export default IImageVolume;
@@ -1,6 +1,6 @@
1
- import { ImageVolume } from './../cache/classes/ImageVolume';
2
1
  import IGeometry from './IGeometry';
3
2
  import IImage from './IImage';
3
+ import IImageVolume from './IImageVolume';
4
4
 
5
5
  /**
6
6
  * ImageLoadObject interface which any imageLoader should return
@@ -19,7 +19,7 @@ export interface IImageLoadObject {
19
19
  */
20
20
  export interface IVolumeLoadObject {
21
21
  /** promise that resolves to an ImageVolume */
22
- promise: Promise<ImageVolume>;
22
+ promise: Promise<IImageVolume>;
23
23
  /** optional cancel function for loading*/
24
24
  cancelFn?: () => void;
25
25
  /** optional decache function */
@@ -6,7 +6,6 @@ import { ActorEntry } from './IActor';
6
6
  import ViewportType from '../enums/ViewportType';
7
7
  import ViewportStatus from '../enums/ViewportStatus';
8
8
  import DisplayArea from './displayArea';
9
- import { IRetrieveConfiguration } from './IRetrieveConfiguration';
10
9
 
11
10
  /**
12
11
  * Viewport interface for cornerstone viewports
@@ -66,6 +65,8 @@ interface IViewport {
66
65
  addActors(actors: Array<ActorEntry>): void;
67
66
  /** add one actor */
68
67
  addActor(actorEntry: ActorEntry): void;
68
+ /** get actor UIDs */
69
+ getActorUIDs(): Array<string>;
69
70
  /** remove all actors from the viewport */
70
71
  removeAllActors(): void;
71
72
  /** remove array of uids */
@@ -1,45 +1,8 @@
1
- import type { vtkImageData } from '@kitware/vtk.js/Common/DataModel/ImageData';
2
- import type Point3 from './Point3';
3
- import type Metadata from './Metadata';
4
- import Mat3 from './Mat3';
5
-
6
- type VolumeScalarData = Float32Array | Uint8Array | Uint16Array | Int16Array;
1
+ import { ImageVolumeProps } from './ImageVolumeProps';
7
2
 
8
3
  /**
9
- * Cornerstone ImageVolume interface.
4
+ * Backwards compatibility for IVolume
10
5
  */
11
- interface IVolume {
12
- /** unique identifier for the volume in the cache */
13
- volumeId: string;
14
- /** volume metadata */
15
- metadata: Metadata;
16
- /** volume dimensions */
17
- dimensions: Point3;
18
- /** volume spacing */
19
- spacing: Point3;
20
- /** volume origin */
21
- origin: Point3;
22
- /** volume direction */
23
- direction: Mat3;
24
- /** volume scalarData */
25
- scalarData: VolumeScalarData | Array<VolumeScalarData>;
26
- /** volume size in bytes */
27
- sizeInBytes?: number;
28
- /** volume image data as vtkImageData */
29
- imageData?: vtkImageData;
30
- /** referencedVolumeId if volume is derived from another volume */
31
- referencedVolumeId?: string;
32
- /** volume scaling metadata */
33
- scaling?: {
34
- PT?: {
35
- // @TODO: Do these values exist?
36
- SUVlbmFactor?: number;
37
- SUVbsaFactor?: number;
38
- // accessed in ProbeTool
39
- suvbwToSuvlbm?: number;
40
- suvbwToSuvbsa?: number;
41
- };
42
- };
43
- }
6
+ type IVolume = ImageVolumeProps;
44
7
 
45
- export { IVolume as default, IVolume, VolumeScalarData };
8
+ export { IVolume };
@@ -0,0 +1,15 @@
1
+ import { VolumeProps } from '.';
2
+
3
+ /**
4
+ * ImageVolume which is considered a special case of a Volume, which is
5
+ * constructed out of set of images (imageIds). Unlike Volume which can be
6
+ * constructed from any type of volumetric data, such as nifti or nrrd,
7
+ */
8
+ interface ImageVolumeProps extends VolumeProps {
9
+ /** imageIds of the volume (if it is built of separate imageIds) */
10
+ imageIds: Array<string>;
11
+ /** if the volume is created from a stack, the imageIds of the stack */
12
+ referencedImageIds?: Array<string>;
13
+ }
14
+
15
+ export { ImageVolumeProps };
@@ -0,0 +1,57 @@
1
+ import type { vtkImageData } from '@kitware/vtk.js/Common/DataModel/ImageData';
2
+ import type Point3 from './Point3';
3
+ import type Metadata from './Metadata';
4
+ import Mat3 from './Mat3';
5
+ import { PixelDataTypedArray } from './PixelDataTypedArray';
6
+
7
+ /**
8
+ * Properties required to instantiate a Volume object.
9
+ * This includes all the necessary data and metadata to define
10
+ * a volume in 3D/4D space.
11
+ */
12
+ interface VolumeProps {
13
+ /** Unique identifier for the volume */
14
+ volumeId: string;
15
+
16
+ /** Metadata describing the volume */
17
+ metadata: Metadata;
18
+
19
+ /** Dimensions of the volume (width, height, depth) */
20
+ dimensions: Point3;
21
+
22
+ /** Spacing between volume points in 3D world space */
23
+ spacing: Point3;
24
+
25
+ /** Origin point of the volume in world space */
26
+ origin: Point3;
27
+
28
+ /** Direction of the volume in world space */
29
+ direction: Mat3;
30
+
31
+ /** Image data representing the volume */
32
+ imageData?: vtkImageData;
33
+
34
+ /** Scalar data representing the volume's intensity values */
35
+ scalarData: PixelDataTypedArray | Array<PixelDataTypedArray>;
36
+
37
+ /** Size of the volume data in bytes (optional) */
38
+ sizeInBytes?: number;
39
+
40
+ /** Property to store additional information */
41
+ additionalDetails?: Record<string, any>;
42
+
43
+ /** Scaling parameters if the volume contains scaled data (optional) */
44
+ scaling?: {
45
+ PT?: {
46
+ SUVlbmFactor?: number;
47
+ SUVbsaFactor?: number;
48
+ suvbwToSuvlbm?: number;
49
+ suvbwToSuvbsa?: number;
50
+ };
51
+ };
52
+
53
+ /** Optional ID of a referenced volume if this volume is derived from another */
54
+ referencedVolumeId?: string;
55
+ }
56
+
57
+ export { VolumeProps };