@cornerstonejs/core 1.30.1 → 1.32.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 (73) hide show
  1. package/dist/cjs/RenderingEngine/StackViewport.js +1 -0
  2. package/dist/cjs/RenderingEngine/StackViewport.js.map +1 -1
  3. package/dist/cjs/RenderingEngine/VideoViewport.d.ts +15 -2
  4. package/dist/cjs/RenderingEngine/VideoViewport.js +97 -33
  5. package/dist/cjs/RenderingEngine/VideoViewport.js.map +1 -1
  6. package/dist/cjs/RenderingEngine/Viewport.js +1 -1
  7. package/dist/cjs/RenderingEngine/Viewport.js.map +1 -1
  8. package/dist/cjs/enums/RequestType.d.ts +2 -1
  9. package/dist/cjs/enums/RequestType.js +1 -0
  10. package/dist/cjs/enums/RequestType.js.map +1 -1
  11. package/dist/cjs/index.d.ts +2 -2
  12. package/dist/cjs/index.js +2 -1
  13. package/dist/cjs/index.js.map +1 -1
  14. package/dist/cjs/init.d.ts +2 -1
  15. package/dist/cjs/init.js +16 -1
  16. package/dist/cjs/init.js.map +1 -1
  17. package/dist/cjs/requestPool/requestPoolManager.d.ts +1 -2
  18. package/dist/cjs/requestPool/requestPoolManager.js +8 -10
  19. package/dist/cjs/requestPool/requestPoolManager.js.map +1 -1
  20. package/dist/cjs/types/IVideoViewport.d.ts +6 -1
  21. package/dist/cjs/utilities/getViewportsWithImageURI.js +6 -5
  22. package/dist/cjs/utilities/getViewportsWithImageURI.js.map +1 -1
  23. package/dist/cjs/webWorkerManager/webWorkerManager.d.ts +21 -0
  24. package/dist/cjs/webWorkerManager/webWorkerManager.js +167 -0
  25. package/dist/cjs/webWorkerManager/webWorkerManager.js.map +1 -0
  26. package/dist/esm/RenderingEngine/StackViewport.js +1 -0
  27. package/dist/esm/RenderingEngine/StackViewport.js.map +1 -1
  28. package/dist/esm/RenderingEngine/VideoViewport.js +97 -33
  29. package/dist/esm/RenderingEngine/VideoViewport.js.map +1 -1
  30. package/dist/esm/RenderingEngine/Viewport.js +1 -1
  31. package/dist/esm/RenderingEngine/Viewport.js.map +1 -1
  32. package/dist/esm/enums/RequestType.js +1 -0
  33. package/dist/esm/enums/RequestType.js.map +1 -1
  34. package/dist/esm/index.js +2 -2
  35. package/dist/esm/index.js.map +1 -1
  36. package/dist/esm/init.js +12 -1
  37. package/dist/esm/init.js.map +1 -1
  38. package/dist/esm/requestPool/requestPoolManager.js +8 -10
  39. package/dist/esm/requestPool/requestPoolManager.js.map +1 -1
  40. package/dist/esm/utilities/getViewportsWithImageURI.js +6 -5
  41. package/dist/esm/utilities/getViewportsWithImageURI.js.map +1 -1
  42. package/dist/esm/webWorkerManager/webWorkerManager.js +132 -0
  43. package/dist/esm/webWorkerManager/webWorkerManager.js.map +1 -0
  44. package/dist/types/RenderingEngine/StackViewport.d.ts.map +1 -1
  45. package/dist/types/RenderingEngine/VideoViewport.d.ts +15 -2
  46. package/dist/types/RenderingEngine/VideoViewport.d.ts.map +1 -1
  47. package/dist/types/enums/RequestType.d.ts +2 -1
  48. package/dist/types/enums/RequestType.d.ts.map +1 -1
  49. package/dist/types/index.d.ts +2 -2
  50. package/dist/types/index.d.ts.map +1 -1
  51. package/dist/types/init.d.ts +2 -1
  52. package/dist/types/init.d.ts.map +1 -1
  53. package/dist/types/requestPool/requestPoolManager.d.ts +1 -2
  54. package/dist/types/requestPool/requestPoolManager.d.ts.map +1 -1
  55. package/dist/types/types/IVideoViewport.d.ts +6 -1
  56. package/dist/types/types/IVideoViewport.d.ts.map +1 -1
  57. package/dist/types/utilities/getViewportsWithImageURI.d.ts.map +1 -1
  58. package/dist/types/webWorkerManager/webWorkerManager.d.ts +22 -0
  59. package/dist/types/webWorkerManager/webWorkerManager.d.ts.map +1 -0
  60. package/dist/umd/index.js +1 -2
  61. package/dist/umd/index.js.map +1 -1
  62. package/package.json +3 -2
  63. package/src/RenderingEngine/StackViewport.ts +1 -0
  64. package/src/RenderingEngine/VideoViewport.ts +146 -28
  65. package/src/RenderingEngine/Viewport.ts +1 -1
  66. package/src/enums/RequestType.ts +3 -1
  67. package/src/index.ts +2 -0
  68. package/src/init.ts +18 -0
  69. package/src/requestPool/requestPoolManager.ts +9 -13
  70. package/src/types/IVideoViewport.ts +44 -4
  71. package/src/utilities/getViewportsWithImageURI.ts +6 -13
  72. package/src/webWorkerManager/webWorkerManager.js +218 -0
  73. package/dist/umd/index.js.LICENSE.txt +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cornerstonejs/core",
3
- "version": "1.30.1",
3
+ "version": "1.32.0",
4
4
  "description": "",
5
5
  "main": "src/index.ts",
6
6
  "types": "dist/types/index.d.ts",
@@ -31,6 +31,7 @@
31
31
  },
32
32
  "dependencies": {
33
33
  "@kitware/vtk.js": "27.3.1",
34
+ "comlink": "^4.4.1",
34
35
  "detect-gpu": "^5.0.22",
35
36
  "gl-matrix": "^3.4.3",
36
37
  "lodash.clonedeep": "4.5.0"
@@ -46,5 +47,5 @@
46
47
  "type": "individual",
47
48
  "url": "https://ohif.org/donate"
48
49
  },
49
- "gitHead": "fd8028a7f840ce13335bc96e014e35aaed8ebc8f"
50
+ "gitHead": "c5094313cbe028576a1d332ed5366f888cdc8d2c"
50
51
  }
@@ -1936,6 +1936,7 @@ class StackViewport extends Viewport implements IStackViewport, IImagesLoader {
1936
1936
  enabled: true,
1937
1937
  },
1938
1938
  useRGBA: true,
1939
+ requestType,
1939
1940
  };
1940
1941
 
1941
1942
  const eventDetail: EventTypes.PreStackNewImageEventDetail = {
@@ -25,6 +25,8 @@ import { getOrCreateCanvas } from './helpers';
25
25
  * looking into an internal scene, and an associated target output `canvas`.
26
26
  */
27
27
  class VideoViewport extends Viewport implements IVideoViewport {
28
+ public static frameRangeExtractor = /(\/frames\/|[&?]frameNumber=)([^/&?]*)/i;
29
+
28
30
  public modality;
29
31
  // Viewport Data
30
32
  protected imageId: string;
@@ -35,11 +37,15 @@ class VideoViewport extends Viewport implements IVideoViewport {
35
37
  private videoWidth = 0;
36
38
  private videoHeight = 0;
37
39
 
38
- private loop = false;
40
+ private loop = true;
39
41
  private mute = true;
40
42
  private isPlaying = false;
41
43
  private scrollSpeed = 1;
42
44
  private playbackRate = 1;
45
+ /**
46
+ * The range is the set of frames to play
47
+ */
48
+ private frameRange: [number, number] = [0, 0];
43
49
 
44
50
  protected metadata;
45
51
 
@@ -50,6 +56,9 @@ class VideoViewport extends Viewport implements IVideoViewport {
50
56
  */
51
57
  private fps = 30;
52
58
 
59
+ /** The number of frames in the video */
60
+ private numberOfFrames = 0;
61
+
53
62
  private videoCamera: InternalVideoCamera = {
54
63
  panWorld: [0, 0],
55
64
  parallelScale: 1,
@@ -156,14 +165,15 @@ class VideoViewport extends Viewport implements IVideoViewport {
156
165
  origin = [0, 0, 0];
157
166
  }
158
167
 
159
- const xSpacing = imagePlaneModule.columnPixelSpacing;
160
- const ySpacing = imagePlaneModule.rowPixelSpacing;
168
+ const xSpacing = imagePlaneModule.columnPixelSpacing || 1;
169
+ const ySpacing = imagePlaneModule.rowPixelSpacing || 1;
161
170
  const xVoxels = imagePlaneModule.columns;
162
171
  const yVoxels = imagePlaneModule.rows;
163
172
 
164
173
  const zSpacing = 1;
165
174
  const zVoxels = 1;
166
175
 
176
+ this.hasPixelSpacing = !!imagePlaneModule.columnPixelSpacing;
167
177
  return {
168
178
  bitsAllocated: 8,
169
179
  numComps: 3,
@@ -171,6 +181,7 @@ class VideoViewport extends Viewport implements IVideoViewport {
171
181
  direction: [...rowCosineVec, ...colCosineVec, ...scanAxisNormal],
172
182
  dimensions: [xVoxels, yVoxels, zVoxels],
173
183
  spacing: [xSpacing, ySpacing, zSpacing],
184
+ hasPixelSpacing: this.hasPixelSpacing,
174
185
  numVoxels: xVoxels * yVoxels * zVoxels,
175
186
  imagePlaneModule,
176
187
  };
@@ -181,23 +192,33 @@ class VideoViewport extends Viewport implements IVideoViewport {
181
192
  * Requirements are to have the imageUrlModule in the metadata
182
193
  * with the rendered endpoint being the raw video in video/mp4 format.
183
194
  */
184
- public setVideo(
185
- imageIds: string | string[],
186
- frameNumber?: number
187
- ): Promise<unknown> {
188
- this.imageId = Array.isArray(imageIds) ? imageIds[0] : imageIds;
189
- const { imageId } = this;
195
+ public setVideo(imageId: string, frameNumber?: number): Promise<unknown> {
196
+ this.imageId = Array.isArray(imageId) ? imageId[0] : imageId;
190
197
  const { rendered } = metaData.get(MetadataModules.IMAGE_URL, imageId);
191
198
  const generalSeries = metaData.get(MetadataModules.GENERAL_SERIES, imageId);
192
199
  this.modality = generalSeries?.Modality;
193
200
  this.metadata = this._getImageDataMetadata();
194
201
 
195
202
  return this.setVideoURL(rendered).then(() => {
196
- const { cineRate = 30 } = metaData.get(MetadataModules.CINE, imageId);
203
+ let { cineRate, numberOfFrames } = metaData.get(
204
+ MetadataModules.CINE,
205
+ imageId
206
+ );
207
+ if (!numberOfFrames) {
208
+ numberOfFrames = Math.round(
209
+ this.videoElement.duration * (cineRate || 30)
210
+ );
211
+ }
212
+ if (!cineRate) {
213
+ cineRate = Math.round(numberOfFrames / this.videoElement.duration);
214
+ }
197
215
  this.fps = cineRate;
216
+ this.numberOfFrames = numberOfFrames;
217
+ // 1 based range setting
218
+ this.setFrameRange([1, numberOfFrames]);
198
219
  if (frameNumber !== undefined) {
199
220
  this.pause();
200
- this.setFrame(frameNumber);
221
+ this.setFrameNumber(frameNumber);
201
222
  }
202
223
  });
203
224
  }
@@ -326,10 +347,31 @@ class VideoViewport extends Viewport implements IVideoViewport {
326
347
  }
327
348
 
328
349
  // Sets the frame number - note according to DICOM, this is 1 based
329
- public async setFrame(frame: number) {
350
+ public async setFrameNumber(frame: number) {
330
351
  this.setTime((frame - 1) / this.fps);
331
352
  }
332
353
 
354
+ /**
355
+ * Sets the playback frame range. The video will play over the given set
356
+ * of frames (assuming it is playing).
357
+ * @param frameRange - the minimum to maximum (inclusive) frames to play over
358
+ * @returns
359
+ */
360
+ public setFrameRange(frameRange: number[]) {
361
+ if (!frameRange) {
362
+ this.frameRange = [1, this.numberOfFrames];
363
+ return;
364
+ }
365
+ if (frameRange.length !== 2 || frameRange[0] === frameRange[1]) {
366
+ return;
367
+ }
368
+ this.frameRange = [frameRange[0], frameRange[1]];
369
+ }
370
+
371
+ public getFrameRange(): [number, number] {
372
+ return this.frameRange;
373
+ }
374
+
333
375
  public setProperties(props: VideoViewportProperties) {
334
376
  if (props.loop !== undefined) {
335
377
  this.videoElement.loop = props.loop;
@@ -421,6 +463,7 @@ class VideoViewport extends Viewport implements IVideoViewport {
421
463
  origin: metadata.origin,
422
464
  direction: metadata.direction,
423
465
  metadata: { Modality: this.modality },
466
+ getScalarData: () => this.getScalarData(),
424
467
  imageData: {
425
468
  getDirection: () => metadata.direction,
426
469
  getDimensions: () => metadata.dimensions,
@@ -445,6 +488,32 @@ class VideoViewport extends Viewport implements IVideoViewport {
445
488
  };
446
489
  }
447
490
 
491
+ /**
492
+ * Checks to see if the imageURI is currently being displayed. The imageURI
493
+ * may contain frame numbers according to the DICOM standard format, which
494
+ * will be stripped to compare the base image URI, and then the values used
495
+ * to check if that frame is currently being displayed.
496
+ *
497
+ * The DICOM standard allows for comma separated values as well, however,
498
+ * this is not supported here, with only a single range or single value
499
+ * being tested.
500
+ *
501
+ * For a single value, the time range +/- 5 frames is permitted to allow
502
+ * the detection to actually succeed when nearby without requiring an exact
503
+ * time frame to be matched.
504
+ *
505
+ * @param imageURI - containing frame number or range.
506
+ * @returns
507
+ */
508
+ public hasImageURI(imageURI: string) {
509
+ // TODO - move annotationFrameRange into core so it can be used here.
510
+ const framesMatch = imageURI.match(VideoViewport.frameRangeExtractor);
511
+ const testURI = framesMatch
512
+ ? imageURI.substring(0, framesMatch.index)
513
+ : imageURI;
514
+ return this.imageId.indexOf(testURI) !== -1;
515
+ }
516
+
448
517
  public setVOI(voiRange: VOIRange): void {
449
518
  this.voiRange = voiRange;
450
519
  this.setColorTransform();
@@ -470,8 +539,6 @@ class VideoViewport extends Viewport implements IVideoViewport {
470
539
  const white = this.averageWhite || [255, 255, 255];
471
540
  const maxWhite = Math.max(...white);
472
541
  const scaleWhite = white.map((c) => maxWhite / c);
473
- // From the DICOM standard: ((x - (c - 0.5)) / (w-1) + 0.5) * (ymax- ymin) + ymin
474
- // which is x/(w-1) - (c - 0.5) / (w-1) + 0.5 for this case
475
542
  const { lower = 0, upper = 255 } = this.voiRange || {};
476
543
  const wlScale = (upper - lower + 1) / 255;
477
544
  const wlDelta = lower / 255;
@@ -496,7 +563,8 @@ class VideoViewport extends Viewport implements IVideoViewport {
496
563
  // NOTE: the parallel scale should be done first
497
564
  // because it affects the focal point later
498
565
  if (camera.parallelScale !== undefined) {
499
- this.videoCamera.parallelScale = 1 / parallelScale;
566
+ this.videoCamera.parallelScale =
567
+ this.element.clientHeight / 2 / parallelScale;
500
568
  }
501
569
 
502
570
  if (focalPoint !== undefined) {
@@ -526,6 +594,33 @@ class VideoViewport extends Viewport implements IVideoViewport {
526
594
  }
527
595
  }
528
596
 
597
+ /**
598
+ * This function returns the imageID associated with either the current
599
+ * frame being displayed, or the range of frames being played. This may not
600
+ * correspond to any particular imageId that has imageId metadata, as the
601
+ * format is one of:
602
+ * `<DICOMweb URI>/frames/<Start Frame>(-<End Frame>)?`
603
+ * or
604
+ * `<Other URI>[?&]frameNumber=<Start Frame>(-<EndFrame>)?`
605
+ * for a URL parameter.
606
+ *
607
+ * @returns an imageID for video
608
+ */
609
+ public getCurrentImageId() {
610
+ const current = this.imageId.replace(
611
+ '/frames/1',
612
+ this.isPlaying
613
+ ? `/frames/1-${this.numberOfFrames}`
614
+ : `/frames/${this.getFrameNumber()}`
615
+ );
616
+ return current;
617
+ }
618
+
619
+ public getFrameNumber() {
620
+ // Need to round this as the fps/time isn't exact
621
+ return 1 + Math.round(this.videoElement.currentTime * this.fps);
622
+ }
623
+
529
624
  public getCamera(): ICamera {
530
625
  const { parallelScale } = this.videoCamera;
531
626
 
@@ -543,7 +638,8 @@ class VideoViewport extends Viewport implements IVideoViewport {
543
638
  parallelProjection: true,
544
639
  focalPoint: canvasCenterWorld,
545
640
  position: [0, 0, 0],
546
- parallelScale: 1 / parallelScale, // Reverse zoom direction back
641
+ viewUp: [0, -1, 0],
642
+ parallelScale: this.element.clientHeight / 2 / parallelScale, // Reverse zoom direction back
547
643
  viewPlaneNormal: [0, 0, 1],
548
644
  };
549
645
  }
@@ -561,7 +657,9 @@ class VideoViewport extends Viewport implements IVideoViewport {
561
657
  };
562
658
 
563
659
  public getNumberOfSlices = (): number => {
564
- return (this.videoElement.duration * this.fps) / this.scrollSpeed;
660
+ return Math.round(
661
+ (this.videoElement.duration * this.fps) / this.scrollSpeed
662
+ );
565
663
  };
566
664
 
567
665
  public getFrameOfReferenceUID = (): string => {
@@ -636,18 +734,23 @@ class VideoViewport extends Viewport implements IVideoViewport {
636
734
  return canvasPos;
637
735
  };
638
736
 
737
+ public getPan(): Point2 {
738
+ const worldPan = this.videoCamera.panWorld;
739
+ return [worldPan[0], worldPan[1]];
740
+ }
741
+
742
+ public getRotation = () => 0;
743
+
639
744
  protected canvasToIndex = (canvasPos: Point2): Point2 => {
640
- const [x, y] = canvasPos;
641
- const ratio = this.videoWidth / this.canvas.width;
642
- const pan = this.getPan();
643
- return [(x + pan[0]) * ratio, (y + pan[1]) * ratio];
745
+ const transform = this.getTransform();
746
+ transform.invert();
747
+
748
+ return transform.transformPoint(canvasPos);
644
749
  };
645
750
 
646
751
  protected indexToCanvas = (indexPos: Point2): Point2 => {
647
- const [x, y] = indexPos;
648
- const ratio = this.canvas.width / this.videoWidth;
649
- const pan = this.getPan();
650
- return [x * ratio - pan[0], y * ratio - pan[1]];
752
+ const transform = this.getTransform();
753
+ return transform.transformPoint(indexPos);
651
754
  };
652
755
 
653
756
  private refreshRenderValues() {
@@ -692,17 +795,15 @@ class VideoViewport extends Viewport implements IVideoViewport {
692
795
  this.renderFrame();
693
796
  };
694
797
 
695
- private renderFrame = () => {
798
+ protected getTransform() {
696
799
  const panWorld: Point2 = this.videoCamera.panWorld;
697
800
  const worldToCanvasRatio: number = this.getWorldToCanvasRatio();
698
801
  const canvasToWorldRatio: number = this.getCanvasToWorldRatio();
699
-
700
802
  const halfCanvas = [this.canvas.width / 2, this.canvas.height / 2];
701
803
  const halfCanvasWorldCoordinates = [
702
804
  halfCanvas[0] * canvasToWorldRatio,
703
805
  halfCanvas[1] * canvasToWorldRatio,
704
806
  ];
705
-
706
807
  const transform = new Transform();
707
808
 
708
809
  // Translate to the center of the canvas (move origin of the transform
@@ -720,6 +821,10 @@ class VideoViewport extends Viewport implements IVideoViewport {
720
821
  -halfCanvasWorldCoordinates[0],
721
822
  -halfCanvasWorldCoordinates[1]
722
823
  );
824
+ return transform;
825
+ }
826
+ private renderFrame = () => {
827
+ const transform = this.getTransform();
723
828
  const transformationMatrix: number[] = transform.getMatrix();
724
829
 
725
830
  this.canvasContext.transform(
@@ -749,6 +854,19 @@ class VideoViewport extends Viewport implements IVideoViewport {
749
854
  time: this.videoElement.currentTime,
750
855
  duration: this.videoElement.duration,
751
856
  });
857
+
858
+ const frame = this.getFrameNumber();
859
+ if (this.isPlaying) {
860
+ if (frame < this.frameRange[0]) {
861
+ this.setFrameNumber(this.frameRange[0]);
862
+ } else if (frame > this.frameRange[1]) {
863
+ if (this.loop) {
864
+ this.setFrameNumber(this.frameRange[0]);
865
+ } else {
866
+ this.pause();
867
+ }
868
+ }
869
+ }
752
870
  };
753
871
 
754
872
  private renderWhilstPlaying = () => {
@@ -1113,7 +1113,7 @@ class Viewport implements IViewport {
1113
1113
  }
1114
1114
 
1115
1115
  if (viewUp) {
1116
- viewUpHasChanged = isEqual(currentViewUp, prevViewUp);
1116
+ viewUpHasChanged = !isEqual(currentViewUp, prevViewUp);
1117
1117
  }
1118
1118
 
1119
1119
  // only modify the clipping planes if the camera is modified out of plane
@@ -6,8 +6,10 @@ enum RequestType {
6
6
  Interaction = 'interaction',
7
7
  /** Second highest priority for loading*/
8
8
  Thumbnail = 'thumbnail',
9
- /** Lowest priority for loading*/
9
+ /** Third highest priority for loading, usually used for image loading in the background*/
10
10
  Prefetch = 'prefetch',
11
+ /** Lower priority, often used for background computations in the worker */
12
+ Compute = 'compute',
11
13
  }
12
14
 
13
15
  export default RequestType;
package/src/index.ts CHANGED
@@ -40,6 +40,7 @@ import {
40
40
  resetUseSharedArrayBuffer,
41
41
  getConfiguration,
42
42
  setConfiguration,
43
+ getWebWorkerManager,
43
44
  } from './init';
44
45
 
45
46
  // Classes
@@ -85,6 +86,7 @@ export {
85
86
  // configs
86
87
  getConfiguration,
87
88
  setConfiguration,
89
+ getWebWorkerManager,
88
90
  // enums
89
91
  Enums,
90
92
  CONSTANTS,
package/src/init.ts CHANGED
@@ -6,6 +6,8 @@ let useSharedArrayBuffer = true;
6
6
  let sharedArrayBufferMode = SharedArrayBufferModes.TRUE;
7
7
  import { deepMerge } from './utilities';
8
8
  import { Cornerstone3DConfig } from './types';
9
+ import CentralizedWebWorkerManager from './webWorkerManager/webWorkerManager';
10
+
9
11
  // TODO: move sharedArrayBuffer into config.
10
12
  // TODO: change config into a class with methods to better control get/set
11
13
  const defaultConfig: Cornerstone3DConfig = {
@@ -36,6 +38,8 @@ let config: Cornerstone3DConfig = {
36
38
  // ...
37
39
  };
38
40
 
41
+ let webWorkerManager = null;
42
+
39
43
  function _getGLContext(): RenderingContext {
40
44
  // Create canvas element. The canvas is not added to the
41
45
  // document itself, so it is never displayed in the
@@ -133,6 +137,11 @@ async function init(configuration = config): Promise<boolean> {
133
137
  setUseSharedArrayBuffer(sharedArrayBufferMode);
134
138
 
135
139
  csRenderInitialized = true;
140
+
141
+ if (!webWorkerManager) {
142
+ webWorkerManager = new CentralizedWebWorkerManager();
143
+ }
144
+
136
145
  return csRenderInitialized;
137
146
  }
138
147
 
@@ -256,6 +265,14 @@ function _updateRenderingPipelinesForAllViewports(): void {
256
265
  );
257
266
  }
258
267
 
268
+ function getWebWorkerManager() {
269
+ if (!webWorkerManager) {
270
+ webWorkerManager = new CentralizedWebWorkerManager();
271
+ }
272
+
273
+ return webWorkerManager;
274
+ }
275
+
259
276
  export {
260
277
  init,
261
278
  getShouldUseCPURendering,
@@ -268,4 +285,5 @@ export {
268
285
  resetUseSharedArrayBuffer,
269
286
  getConfiguration,
270
287
  setConfiguration,
288
+ getWebWorkerManager,
271
289
  };
@@ -78,12 +78,14 @@ class RequestPoolManager {
78
78
  interaction: 0,
79
79
  thumbnail: 0,
80
80
  prefetch: 0,
81
+ compute: 0,
81
82
  };
82
83
  /* maximum number of requests of each type. */
83
84
  public maxNumRequests: {
84
85
  interaction: number;
85
86
  thumbnail: number;
86
87
  prefetch: number;
88
+ compute: number;
87
89
  };
88
90
  /* A public property that is used to set the delay between requests. */
89
91
  public grabDelay: number;
@@ -101,6 +103,7 @@ class RequestPoolManager {
101
103
  interaction: { 0: [] },
102
104
  thumbnail: { 0: [] },
103
105
  prefetch: { 0: [] },
106
+ compute: { 0: [] },
104
107
  };
105
108
 
106
109
  this.grabDelay = 5;
@@ -110,12 +113,14 @@ class RequestPoolManager {
110
113
  interaction: 0,
111
114
  thumbnail: 0,
112
115
  prefetch: 0,
116
+ compute: 0,
113
117
  };
114
118
 
115
119
  this.maxNumRequests = {
116
120
  interaction: 6,
117
121
  thumbnail: 6,
118
122
  prefetch: 5,
123
+ compute: 15,
119
124
  };
120
125
  }
121
126
 
@@ -185,15 +190,7 @@ class RequestPoolManager {
185
190
  // Adding the request to the correct priority group of the request type
186
191
  this.requestPool[type][priority].push(requestDetails);
187
192
 
188
- // Wake up
189
- if (!this.awake) {
190
- this.awake = true;
191
- this.startGrabbing();
192
- } else if (type === RequestType.Interaction) {
193
- // Todo: this is a hack for interaction right now, we should separate
194
- // the grabbing from the adding requests
195
- this.startGrabbing();
196
- }
193
+ this.startGrabbing();
197
194
  }
198
195
 
199
196
  /**
@@ -273,11 +270,13 @@ class RequestPoolManager {
273
270
  const hasRemainingPrefetchRequests = this.sendRequests(
274
271
  RequestType.Prefetch
275
272
  );
273
+ const hasRemainingComputeRequests = this.sendRequests(RequestType.Compute);
276
274
 
277
275
  if (
278
276
  !hasRemainingInteractionRequests &&
279
277
  !hasRemainingThumbnailRequests &&
280
- !hasRemainingPrefetchRequests
278
+ !hasRemainingPrefetchRequests &&
279
+ !hasRemainingComputeRequests
281
280
  ) {
282
281
  this.awake = false;
283
282
  }
@@ -323,7 +322,4 @@ class RequestPoolManager {
323
322
  }
324
323
  }
325
324
 
326
- const requestPoolManager = new RequestPoolManager();
327
-
328
325
  export { RequestPoolManager };
329
- export default requestPoolManager;
@@ -19,11 +19,26 @@ export default interface IVideoViewport extends IViewport {
19
19
  */
20
20
  getProperties: () => VideoViewportProperties;
21
21
 
22
- setVideo: (
23
- imageIds: string | string[],
24
- imageIdIndex?: number
25
- ) => Promise<unknown>;
22
+ /**
23
+ * Sets the video to play.
24
+ * The video should have at least some metadata in the metadata provider,
25
+ * including:
26
+ * * study/series/sop common module for UIDs
27
+ * * `cineModule` for information on number of frames and playback rate
28
+ * * `imageUrlModule` - to get the URL for the image under the `rendered` attribute
29
+ *
30
+ * Without these, other tools requiring metadata wont work, although basic
31
+ * playback does work if the setVideoURL is used instead.
32
+ */
33
+ setVideo: (imageIds: string, imageIdIndex?: number) => Promise<unknown>;
26
34
 
35
+ /**
36
+ * Displays a raw video, without any metadata associated with it. Plays back,
37
+ * but does not permit tools to apply to the viewport, which requires providing
38
+ * additional metadata for the study.
39
+ *
40
+ * @param url - to display
41
+ */
27
42
  setVideoURL: (url: string) => void;
28
43
 
29
44
  play: () => void;
@@ -35,6 +50,31 @@ export default interface IVideoViewport extends IViewport {
35
50
  */
36
51
  resetProperties(): void;
37
52
 
53
+ /**
54
+ * Gets the current image id, including frame selction or frameless.
55
+ */
56
+ getCurrentImageId(): string;
57
+
58
+ /**
59
+ * Gets the current frame, 1 based
60
+ */
61
+ getFrameNumber(): number;
62
+
63
+ /**
64
+ * Sets the current frame
65
+ */
66
+ setFrameNumber(frameNo: number);
67
+
68
+ /**
69
+ * Sets the range of frames for displaying. This is the range of frames
70
+ * that are shown/looped over when the video is playing.
71
+ * Note that ability to playback a frame range depends on the server
72
+ * implementing byte range requests, OR the video being easily cached in memory.
73
+ */
74
+ setFrameRange(range?: [number, number]);
75
+
76
+ getFrameRange(): [number, number];
77
+
38
78
  /**
39
79
  * Centers Pan and resets the zoom for stack viewport.
40
80
  */
@@ -26,20 +26,13 @@ export default function getViewportsWithImageURI(
26
26
 
27
27
  const viewports = [];
28
28
  renderingEngines.forEach((renderingEngine) => {
29
- const stackViewports = renderingEngine.getStackViewports();
29
+ const viewportsForRenderingEngine = renderingEngine.getViewports();
30
30
 
31
- const filteredStackViewports = stackViewports.filter((viewport) =>
32
- viewport.hasImageURI(imageURI)
33
- );
34
-
35
- // If no stack viewport found but a volumeViewport is rendering the same data
36
- const volumeViewports = renderingEngine.getVolumeViewports();
37
-
38
- const filteredVolumeViewports = volumeViewports.filter((viewport) =>
39
- viewport.hasImageURI(imageURI)
40
- );
41
-
42
- viewports.push(...filteredStackViewports, ...filteredVolumeViewports);
31
+ viewportsForRenderingEngine.forEach((viewport) => {
32
+ if (viewport.hasImageURI(imageURI)) {
33
+ viewports.push(viewport);
34
+ }
35
+ });
43
36
  });
44
37
 
45
38
  return viewports;