@cornerstonejs/core 1.69.0 → 1.70.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 (115) hide show
  1. package/dist/cjs/RenderingEngine/BaseVolumeViewport.d.ts +3 -3
  2. package/dist/cjs/RenderingEngine/BaseVolumeViewport.js +36 -17
  3. package/dist/cjs/RenderingEngine/BaseVolumeViewport.js.map +1 -1
  4. package/dist/cjs/RenderingEngine/CanvasActor/index.js +1 -1
  5. package/dist/cjs/RenderingEngine/CanvasActor/index.js.map +1 -1
  6. package/dist/cjs/RenderingEngine/RenderingEngine.js +8 -26
  7. package/dist/cjs/RenderingEngine/RenderingEngine.js.map +1 -1
  8. package/dist/cjs/RenderingEngine/StackViewport.d.ts +5 -4
  9. package/dist/cjs/RenderingEngine/StackViewport.js +46 -24
  10. package/dist/cjs/RenderingEngine/StackViewport.js.map +1 -1
  11. package/dist/cjs/RenderingEngine/VideoViewport.d.ts +2 -2
  12. package/dist/cjs/RenderingEngine/VideoViewport.js +5 -9
  13. package/dist/cjs/RenderingEngine/VideoViewport.js.map +1 -1
  14. package/dist/cjs/RenderingEngine/Viewport.d.ts +17 -7
  15. package/dist/cjs/RenderingEngine/Viewport.js +173 -64
  16. package/dist/cjs/RenderingEngine/Viewport.js.map +1 -1
  17. package/dist/cjs/RenderingEngine/helpers/getOrCreateCanvas.d.ts +1 -0
  18. package/dist/cjs/RenderingEngine/helpers/getOrCreateCanvas.js +15 -2
  19. package/dist/cjs/RenderingEngine/helpers/getOrCreateCanvas.js.map +1 -1
  20. package/dist/cjs/cache/cache.js +0 -1
  21. package/dist/cjs/cache/cache.js.map +1 -1
  22. package/dist/cjs/loaders/volumeLoader.js +1 -1
  23. package/dist/cjs/loaders/volumeLoader.js.map +1 -1
  24. package/dist/cjs/types/IViewport.d.ts +18 -0
  25. package/dist/cjs/types/ViewportProperties.d.ts +1 -2
  26. package/dist/cjs/types/displayArea.d.ts +5 -1
  27. package/dist/cjs/types/index.d.ts +2 -2
  28. package/dist/cjs/utilities/index.d.ts +2 -1
  29. package/dist/cjs/utilities/index.js +3 -1
  30. package/dist/cjs/utilities/index.js.map +1 -1
  31. package/dist/cjs/utilities/loadImageToCanvas.d.ts +6 -2
  32. package/dist/cjs/utilities/loadImageToCanvas.js +14 -2
  33. package/dist/cjs/utilities/loadImageToCanvas.js.map +1 -1
  34. package/dist/cjs/utilities/renderToCanvasCPU.d.ts +2 -2
  35. package/dist/cjs/utilities/renderToCanvasCPU.js +1 -1
  36. package/dist/cjs/utilities/renderToCanvasCPU.js.map +1 -1
  37. package/dist/cjs/utilities/renderToCanvasGPU.d.ts +2 -2
  38. package/dist/cjs/utilities/renderToCanvasGPU.js +31 -12
  39. package/dist/cjs/utilities/renderToCanvasGPU.js.map +1 -1
  40. package/dist/esm/RenderingEngine/BaseVolumeViewport.js +37 -18
  41. package/dist/esm/RenderingEngine/BaseVolumeViewport.js.map +1 -1
  42. package/dist/esm/RenderingEngine/CanvasActor/index.js +1 -1
  43. package/dist/esm/RenderingEngine/CanvasActor/index.js.map +1 -1
  44. package/dist/esm/RenderingEngine/RenderingEngine.js +8 -26
  45. package/dist/esm/RenderingEngine/RenderingEngine.js.map +1 -1
  46. package/dist/esm/RenderingEngine/StackViewport.js +47 -25
  47. package/dist/esm/RenderingEngine/StackViewport.js.map +1 -1
  48. package/dist/esm/RenderingEngine/VideoViewport.js +5 -9
  49. package/dist/esm/RenderingEngine/VideoViewport.js.map +1 -1
  50. package/dist/esm/RenderingEngine/Viewport.js +173 -64
  51. package/dist/esm/RenderingEngine/Viewport.js.map +1 -1
  52. package/dist/esm/RenderingEngine/helpers/getOrCreateCanvas.js +14 -1
  53. package/dist/esm/RenderingEngine/helpers/getOrCreateCanvas.js.map +1 -1
  54. package/dist/esm/cache/cache.js +0 -1
  55. package/dist/esm/cache/cache.js.map +1 -1
  56. package/dist/esm/loaders/volumeLoader.js +1 -1
  57. package/dist/esm/loaders/volumeLoader.js.map +1 -1
  58. package/dist/esm/utilities/index.js +2 -1
  59. package/dist/esm/utilities/index.js.map +1 -1
  60. package/dist/esm/utilities/loadImageToCanvas.js +14 -2
  61. package/dist/esm/utilities/loadImageToCanvas.js.map +1 -1
  62. package/dist/esm/utilities/renderToCanvasCPU.js +1 -1
  63. package/dist/esm/utilities/renderToCanvasCPU.js.map +1 -1
  64. package/dist/esm/utilities/renderToCanvasGPU.js +8 -9
  65. package/dist/esm/utilities/renderToCanvasGPU.js.map +1 -1
  66. package/dist/types/RenderingEngine/BaseVolumeViewport.d.ts +3 -3
  67. package/dist/types/RenderingEngine/BaseVolumeViewport.d.ts.map +1 -1
  68. package/dist/types/RenderingEngine/CanvasActor/index.d.ts.map +1 -1
  69. package/dist/types/RenderingEngine/RenderingEngine.d.ts.map +1 -1
  70. package/dist/types/RenderingEngine/StackViewport.d.ts +5 -4
  71. package/dist/types/RenderingEngine/StackViewport.d.ts.map +1 -1
  72. package/dist/types/RenderingEngine/VideoViewport.d.ts +2 -2
  73. package/dist/types/RenderingEngine/VideoViewport.d.ts.map +1 -1
  74. package/dist/types/RenderingEngine/Viewport.d.ts +17 -7
  75. package/dist/types/RenderingEngine/Viewport.d.ts.map +1 -1
  76. package/dist/types/RenderingEngine/helpers/getOrCreateCanvas.d.ts +1 -0
  77. package/dist/types/RenderingEngine/helpers/getOrCreateCanvas.d.ts.map +1 -1
  78. package/dist/types/cache/cache.d.ts.map +1 -1
  79. package/dist/types/loaders/volumeLoader.d.ts.map +1 -1
  80. package/dist/types/types/IViewport.d.ts +18 -0
  81. package/dist/types/types/IViewport.d.ts.map +1 -1
  82. package/dist/types/types/ViewportProperties.d.ts +1 -2
  83. package/dist/types/types/ViewportProperties.d.ts.map +1 -1
  84. package/dist/types/types/displayArea.d.ts +5 -1
  85. package/dist/types/types/displayArea.d.ts.map +1 -1
  86. package/dist/types/types/index.d.ts +2 -2
  87. package/dist/types/types/index.d.ts.map +1 -1
  88. package/dist/types/utilities/index.d.ts +2 -1
  89. package/dist/types/utilities/index.d.ts.map +1 -1
  90. package/dist/types/utilities/loadImageToCanvas.d.ts +6 -2
  91. package/dist/types/utilities/loadImageToCanvas.d.ts.map +1 -1
  92. package/dist/types/utilities/renderToCanvasCPU.d.ts +2 -2
  93. package/dist/types/utilities/renderToCanvasCPU.d.ts.map +1 -1
  94. package/dist/types/utilities/renderToCanvasGPU.d.ts +2 -2
  95. package/dist/types/utilities/renderToCanvasGPU.d.ts.map +1 -1
  96. package/dist/umd/index.js +1 -1
  97. package/dist/umd/index.js.map +1 -1
  98. package/package.json +2 -2
  99. package/src/RenderingEngine/BaseVolumeViewport.ts +30 -6
  100. package/src/RenderingEngine/CanvasActor/index.ts +2 -1
  101. package/src/RenderingEngine/RenderingEngine.ts +11 -35
  102. package/src/RenderingEngine/StackViewport.ts +55 -14
  103. package/src/RenderingEngine/VideoViewport.ts +14 -9
  104. package/src/RenderingEngine/Viewport.ts +353 -91
  105. package/src/RenderingEngine/helpers/getOrCreateCanvas.ts +32 -1
  106. package/src/cache/cache.ts +2 -1
  107. package/src/loaders/volumeLoader.ts +2 -1
  108. package/src/types/IViewport.ts +130 -10
  109. package/src/types/ViewportProperties.ts +1 -3
  110. package/src/types/displayArea.ts +6 -1
  111. package/src/types/index.ts +4 -0
  112. package/src/utilities/index.ts +2 -0
  113. package/src/utilities/loadImageToCanvas.ts +38 -3
  114. package/src/utilities/renderToCanvasCPU.ts +7 -2
  115. package/src/utilities/renderToCanvasGPU.ts +20 -14
@@ -3,13 +3,14 @@ import '@kitware/vtk.js/Rendering/Profiles/Volume';
3
3
  import vtkImageData from '@kitware/vtk.js/Common/DataModel/ImageData';
4
4
  import type { vtkImageData as vtkImageDataType } from '@kitware/vtk.js/Common/DataModel/ImageData';
5
5
  import vtkDataArray from '@kitware/vtk.js/Common/Core/DataArray';
6
- import cloneDeep from 'lodash.clonedeep';
7
6
 
8
7
  import { ImageVolume } from '../cache/classes/ImageVolume';
9
8
  import cache from '../cache/cache';
10
9
  import Events from '../enums/Events';
11
10
  import eventTarget from '../eventTarget';
12
11
  import triggerEvent from '../utilities/triggerEvent';
12
+ import cloneDeep from 'lodash.clonedeep';
13
+
13
14
  import {
14
15
  generateVolumePropsFromImageIds,
15
16
  getBufferConfiguration,
@@ -11,8 +11,8 @@ import BoundsLPS from './BoundsLPS';
11
11
  /**
12
12
  * Specifies what view to get a reference for.
13
13
  * This set of options allows a Viewport to return a reference for an image
14
- * not currently in view, such as for a different slice, or for a given set of
15
- * points.
14
+ * not currently in view, such as for a different slice, or containing a given
15
+ * set of points.
16
16
  */
17
17
  export type ViewReferenceSpecifier = {
18
18
  /** The slice index within the current viewport camera to get a reference for */
@@ -31,9 +31,12 @@ export type ViewReferenceSpecifier = {
31
31
  };
32
32
 
33
33
  /**
34
- * These are the options arguments to determine whether a view reference
35
- * is compatible with a viewport, that is, could be or is shown in a viewport.
36
- * That specifies whether a view could be shown in a given viewport or not.
34
+ * It is often important to decide if a given view can display a specific
35
+ * view reference. For example, annotations need to know if they are
36
+ * shown on a view. Some operations need to know if the view COULD show
37
+ * the given object if certain changes were made to the view. This object
38
+ * allows specifying what changes are permitted in order to determine if the
39
+ * view could show the image.
37
40
  */
38
41
  export type ReferenceCompatibleOptions = {
39
42
  /**
@@ -61,9 +64,10 @@ export type ReferenceCompatibleOptions = {
61
64
  };
62
65
 
63
66
  /**
64
- * A view reference references the image/location of an image. It
65
- * basically says would this viewport show this view, or can direct a viewport
66
- * to show a specific view.
67
+ * A view reference references the image/location of an image. Typical use
68
+ * cases include remembering the current position of a viewport to allow returning
69
+ * to it later, as well as determining whether specific views should show annotations
70
+ * or other overlay information.
67
71
  */
68
72
  export type ViewReference = {
69
73
  /**
@@ -105,6 +109,82 @@ export type ViewReference = {
105
109
  bounds?: BoundsLPS;
106
110
  };
107
111
 
112
+ /**
113
+ * A view presentation stores information about how the view is presented to the
114
+ * user, such as rotation, the displayed area, pan/zoom etc. This is represented
115
+ * as values which are independent of the view type or size as much as possible,
116
+ * by normalizing the values to the type of view presented. This allows
117
+ * remember or synchronizing values in a much wider variety of places than
118
+ * using the raw/underlying view data such as camera position.
119
+ */
120
+ export type ViewPresentation = {
121
+ /**
122
+ * The slice thickness - in frames(true/default) it will be 1 for a frame distance of
123
+ * 1 pixel thickness, while for mm will be in mm distance.
124
+ */
125
+ slabThickness?: number;
126
+
127
+ /**
128
+ * The rotation of the view - this is related to cameraViewUp, but is relative
129
+ * to the viewNormal and the default viewUp for that viewNormal.
130
+ */
131
+ rotation?: number;
132
+
133
+ /**
134
+ * The display area being shown. This is more consistent than applying a set
135
+ * of boundary areas.
136
+ */
137
+ displayArea?: DisplayArea;
138
+
139
+ /**
140
+ * The zoom value is a zoom factor relative either to fit to canvas or relative
141
+ * to the display area.
142
+ * The default true units are relative to the initial camera
143
+ * scale to fit is used to get units relative to the scale to fit camera.
144
+ */
145
+ zoom?: number;
146
+
147
+ /**
148
+ * The pan value is how far the pan has moved relative to the fit to canvas
149
+ * or relative to the display area initial position/sizing.
150
+ * true is the default units, which is relative to the initial canvas setting,
151
+ * in zoom relative units.
152
+ */
153
+ pan?: Point2;
154
+ };
155
+
156
+ /**
157
+ * A view presentation selector allows choosing what view attributes should be
158
+ * returned by a call to getViewPresentation. This allows a shared selection
159
+ * object to be used to specify which presentation attributes are to be used.
160
+ *
161
+ * For example, a synchronizer might choose to use a presentation selector
162
+ * so that multiple viewports could specify to synchronizer, say slabThickness
163
+ * and windowLevel across one set, while a different synchronizer would choose
164
+ * to apply zoom and pan.
165
+ * Then, a resize operation might choose to synchronize display area, zoom and pan, but
166
+ * not window level or slab thickness.
167
+ * A store/remember state of viewport might choose to synchronize everything
168
+ * Individual tools might choose to use synchronization of the specific attribute
169
+ * which they are modifying (such as rotation) for history undo/redo, but use the
170
+ * same re-apply function to undo the remembered history.
171
+ *
172
+ * It is certainly possible to implement each of these with their own selectors
173
+ * which call the particular get/set functions, but that makes it more work to
174
+ * share particular sets for different uses.
175
+ */
176
+ export type ViewPresentationSelector = {
177
+ slabThickness?: boolean;
178
+ // Camera relative parameters
179
+ rotation?: boolean;
180
+ displayArea?: boolean;
181
+ zoom?: boolean;
182
+ pan?: boolean;
183
+ // Transfer function relative parameters
184
+ windowLevel?: boolean;
185
+ paletteLut?: boolean;
186
+ };
187
+
108
188
  /**
109
189
  * Viewport interface for cornerstone viewports
110
190
  */
@@ -210,8 +290,13 @@ interface IViewport {
210
290
  /** Gets a referenced image url of some sort - could be a real image id, or could be a URL with parameters */
211
291
  getReferenceId(viewRefSpecifier?: ViewReferenceSpecifier): string;
212
292
  /**
213
- * Gets a view target, allowing comparison between view positions as well
214
- * as restoring views later.
293
+ * Gets a view target specifying WHAT a view is displaying,
294
+ * allowing for checking if a given image is displayed or could be displayed
295
+ * in a given viewport.
296
+ * See getViewPresentation for HOW a view is displayed.
297
+ *
298
+ * @param viewRefSpecifier - choose an alternate view to be specified, typically
299
+ * a different slice index in the same set of images.
215
300
  */
216
301
  getViewReference(viewRefSpecifier?: ViewReferenceSpecifier): ViewReference;
217
302
  /**
@@ -225,6 +310,41 @@ interface IViewport {
225
310
  viewRef: ViewReference,
226
311
  options?: ReferenceCompatibleOptions
227
312
  ): boolean;
313
+ /**
314
+ * Gets a view presentation information specifying HOW a viewport displays
315
+ * something, but not what is being displayed.
316
+ * See getViewReference to get information on WHAT is being displayed.
317
+ *
318
+ * This is intended to have information on how an image is presented to the user, without
319
+ * specifying what image s displayed. All of this information is available
320
+ * externally, but this method combines the parts of this that are appropriate
321
+ * for remember or applying to other views, without necessarily needing to know
322
+ * what all the atributes are. That differs from methods like getCamera which
323
+ * fetch exact view details that are not likely to be identical between viewports
324
+ * as they change sizes or apply to different images.
325
+ *
326
+ * Note that the results of this can be used on different viewports, for example,
327
+ * the pan values can be applied to a volume viewport showing a CT, and a
328
+ * stack viewport showing an ultrasound.
329
+ *
330
+ * The selector allows choosing which view presentation attributes to return.
331
+ * Some default values are available from `Viewport.CameraViewPresentation` and
332
+ * `Viewport.TransferViewPresentation`
333
+ *
334
+ * @param viewPresSel - select which attributes to display.
335
+ */
336
+ getViewPresentation(viewPresSel?: ViewPresentationSelector): ViewPresentation;
337
+ /**
338
+ * Selects both what a viewport is showing (which image/slice) as well as how it
339
+ * is being presented. If only one or the other values is provided, the
340
+ * currently applied view for the other attribute is preserved, allowing for
341
+ * remember specific sets of attributes.
342
+ *
343
+ * @param viewRef - the basic positioning in terms of what image id/slice index/orientation to display
344
+ * * The viewRef must be applicable to the current stack or volume, otherwise an exception will be thrown
345
+ * @param viewPres - the presentation information to apply to the current image (as chosen above)
346
+ */
347
+ setView(viewRef?: ViewReference, viewPres?: ViewPresentation);
228
348
 
229
349
  /** whether the viewport has custom rendering */
230
350
  customRenderViewportToCanvas: () => unknown;
@@ -5,7 +5,7 @@ import { ColormapPublic } from './Colormap';
5
5
  /**
6
6
  * Shared Viewport Properties between Stack and Volume Viewports
7
7
  */
8
- type ViewportProperties = {
8
+ export type ViewportProperties = {
9
9
  /** voi range (upper, lower) for the viewport */
10
10
  voiRange?: VOIRange;
11
11
  /** VOILUTFunction type which is LINEAR or SAMPLED_SIGMOID */
@@ -19,5 +19,3 @@ type ViewportProperties = {
19
19
  /**Rotation of the camera */
20
20
  rotation?: number;
21
21
  };
22
-
23
- export type { ViewportProperties };
@@ -1,8 +1,13 @@
1
+ import InterpolationType from '../enums/InterpolationType';
2
+
1
3
  type DisplayArea = {
4
+ type?: 'SCALE' | 'FIT';
5
+ scale?: number;
6
+ interpolationType?: InterpolationType;
2
7
  imageArea?: [number, number]; // areaX, areaY
3
8
  imageCanvasPoint?: {
4
9
  imagePoint: [number, number]; // imageX, imageY
5
- canvasPoint: [number, number]; // canvasX, canvasY
10
+ canvasPoint?: [number, number]; // canvasX, canvasY
6
11
  };
7
12
  storeAsInitialCamera?: boolean;
8
13
  };
@@ -19,6 +19,8 @@ import type {
19
19
  ViewReferenceSpecifier,
20
20
  ReferenceCompatibleOptions,
21
21
  ViewReference,
22
+ ViewPresentation,
23
+ ViewPresentationSelector,
22
24
  } from './IViewport';
23
25
  import type {
24
26
  VolumeActor,
@@ -161,6 +163,8 @@ export type {
161
163
  IStreamingVolumeProperties,
162
164
  IViewport,
163
165
  ViewReference,
166
+ ViewPresentation,
167
+ ViewPresentationSelector,
164
168
  ReferenceCompatibleOptions,
165
169
  ViewReferenceSpecifier,
166
170
  StackViewportProperties,
@@ -78,6 +78,7 @@ import * as windowLevel from './windowLevel';
78
78
  import * as colormap from './colormap';
79
79
  import * as transferFunctionUtils from './transferFunctionUtils';
80
80
  import * as cacheUtils from './cacheUtils';
81
+ import * as color from './color';
81
82
 
82
83
  export {
83
84
  eventListener,
@@ -160,4 +161,5 @@ export {
160
161
  getViewportImageIds,
161
162
  getRandomSampleFromArray,
162
163
  getVolumeId,
164
+ color,
163
165
  };
@@ -1,4 +1,4 @@
1
- import { IImage } from '../types';
1
+ import type { IImage, ViewportInputOptions } from '../types';
2
2
 
3
3
  import { loadAndCacheImage } from '../loaders/imageLoader';
4
4
  import * as metaData from '../metaData';
@@ -8,13 +8,22 @@ import renderToCanvasGPU from './renderToCanvasGPU';
8
8
  import renderToCanvasCPU from './renderToCanvasCPU';
9
9
  import { getConfiguration } from '../init';
10
10
 
11
- interface LoadImageOptions {
11
+ export interface LoadImageOptions {
12
12
  canvas: HTMLCanvasElement;
13
13
  imageId: string;
14
14
  requestType?: RequestType;
15
15
  priority?: number;
16
16
  renderingEngineId?: string;
17
17
  useCPURendering?: boolean;
18
+ // Render a thumbnail in a 256x256 viewport
19
+ // Also set imageAspect to render thumbnail in an aspect ratio width viewport
20
+ thumbnail?: boolean;
21
+ // Sets the CSS width to the image aspect ratio
22
+ imageAspect?: boolean;
23
+ // Sets the canvas pixel size to the physical pixel size of the image area
24
+ physicalPixels?: boolean;
25
+ // Sets the viewport input options Defaults to scale to fit 110%
26
+ viewportOptions?: ViewportInputOptions;
18
27
  }
19
28
 
20
29
  /**
@@ -35,6 +44,9 @@ interface LoadImageOptions {
35
44
  * the order of loading for the pool manager is interaction, thumbnail, prefetch
36
45
  * @param priority - The priority of the request within the request type (lower is higher priority)
37
46
  * @param useCPURendering - Force the use of the CPU rendering pipeline (default to false)
47
+ * @param thumbnail - Render a thumbnail image
48
+ * @param imageAspect - assign the width based on the aspect ratio of the image
49
+ * @param physicalPixels - set the width/height to the physical pixel size
38
50
  * @returns - A promise that resolves when the image has been rendered with the imageId
39
51
  */
40
52
  export default function loadImageToCanvas(
@@ -47,8 +59,13 @@ export default function loadImageToCanvas(
47
59
  priority = -5,
48
60
  renderingEngineId = '_thumbnails',
49
61
  useCPURendering = false,
62
+ thumbnail = false,
63
+ imageAspect = false,
64
+ physicalPixels = false,
65
+ viewportOptions,
50
66
  } = options;
51
67
 
68
+ const devicePixelRatio = window.devicePixelRatio || 1;
52
69
  const renderFn = useCPURendering ? renderToCanvasCPU : renderToCanvasGPU;
53
70
 
54
71
  return new Promise((resolve, reject) => {
@@ -57,7 +74,25 @@ export default function loadImageToCanvas(
57
74
 
58
75
  image.isPreScaled = image.isPreScaled || image.preScale?.scaled;
59
76
 
60
- renderFn(canvas, image, modality, renderingEngineId).then(() => {
77
+ if (thumbnail) {
78
+ canvas.height = 256;
79
+ canvas.width = 256;
80
+ }
81
+ if (physicalPixels) {
82
+ canvas.width = canvas.offsetWidth * devicePixelRatio;
83
+ canvas.height = canvas.offsetHeight * devicePixelRatio;
84
+ }
85
+ if (imageAspect) {
86
+ canvas.width = (canvas.height * image.width) / image.height;
87
+ }
88
+
89
+ renderFn(
90
+ canvas,
91
+ image,
92
+ modality,
93
+ renderingEngineId,
94
+ viewportOptions
95
+ ).then(() => {
61
96
  resolve(imageId);
62
97
  });
63
98
  }
@@ -1,4 +1,8 @@
1
- import { IImage, CPUFallbackEnabledElement } from '../types';
1
+ import {
2
+ IImage,
3
+ CPUFallbackEnabledElement,
4
+ ViewportInputOptions,
5
+ } from '../types';
2
6
 
3
7
  import getDefaultViewport from '../RenderingEngine/helpers/cpuFallback/rendering/getDefaultViewport';
4
8
  import calculateTransform from '../RenderingEngine/helpers/cpuFallback/rendering/calculateTransform';
@@ -15,7 +19,8 @@ export default function renderToCanvasCPU(
15
19
  canvas: HTMLCanvasElement,
16
20
  image: IImage,
17
21
  modality?: string,
18
- renderingEngineId?: string
22
+ _renderingEngineId?: string,
23
+ _viewportOptions?: ViewportInputOptions
19
24
  ): Promise<string> {
20
25
  const viewport = getDefaultViewport(canvas, image, modality);
21
26
 
@@ -1,7 +1,9 @@
1
- import getOrCreateCanvas from '../RenderingEngine/helpers/getOrCreateCanvas';
1
+ import getOrCreateCanvas, {
2
+ EPSILON,
3
+ } from '../RenderingEngine/helpers/getOrCreateCanvas';
2
4
  import { ViewportType, Events } from '../enums';
3
5
  import StackViewport from '../RenderingEngine/StackViewport';
4
- import { IImage } from '../types';
6
+ import { IImage, ViewportInputOptions } from '../types';
5
7
  import { getRenderingEngine } from '../RenderingEngine/getRenderingEngine';
6
8
  import RenderingEngine from '../RenderingEngine';
7
9
  import isPTPrescaledWithSUV from './isPTPrescaledWithSUV';
@@ -29,7 +31,8 @@ export default function renderToCanvasGPU(
29
31
  canvas: HTMLCanvasElement,
30
32
  image: IImage,
31
33
  modality = undefined,
32
- renderingEngineId = '_thumbnails'
34
+ renderingEngineId = '_thumbnails',
35
+ viewportOptions: ViewportInputOptions = { displayArea: { imageArea: [1, 1] } }
33
36
  ): Promise<string> {
34
37
  if (!canvas || !(canvas instanceof HTMLCanvasElement)) {
35
38
  throw new Error('canvas element is required');
@@ -39,21 +42,24 @@ export default function renderToCanvasGPU(
39
42
  const viewportId = `renderGPUViewport-${imageIdToPrint}`;
40
43
  const imageId = image.imageId;
41
44
  const element = document.createElement('div');
42
- element.style.width = `${canvas.width}px`;
43
- element.style.height = `${canvas.height}px`;
45
+ const devicePixelRatio = window.devicePixelRatio || 1;
46
+ const originalWidth = canvas.width;
47
+ const originalHeight = canvas.height;
48
+ // The canvas width/height are set by flooring the CSS size converted
49
+ // into physical pixels, but because these are float values, the conversion
50
+ // isn't exact, and using the exact value sometimes leads to an off by 1
51
+ // in the actual size, so adding EPSILON to the size resolves
52
+ // the problem.
53
+ element.style.width = `${originalWidth + EPSILON}px`;
54
+ element.style.height = `${originalHeight + EPSILON}px`;
44
55
  element.style.visibility = 'hidden';
45
56
  element.style.position = 'absolute';
46
57
 
47
58
  // Up-sampling the provided canvas to match the device pixel ratio
48
59
  // since we use device pixel ratio to determine the size of the canvas
49
60
  // inside the rendering engine.
50
- const devicePixelRatio = window.devicePixelRatio || 1;
51
- const originalWidth = canvas.width;
52
- const originalHeight = canvas.height;
53
61
  canvas.width = originalWidth * devicePixelRatio;
54
62
  canvas.height = originalHeight * devicePixelRatio;
55
- canvas.style.width = `${originalWidth}px`;
56
- canvas.style.height = `${originalHeight}px`;
57
63
 
58
64
  document.body.appendChild(element);
59
65
 
@@ -61,6 +67,8 @@ export default function renderToCanvasGPU(
61
67
  const uniqueId = viewportId.split(':').join('-');
62
68
  element.setAttribute('viewport-id-for-remove', uniqueId);
63
69
 
70
+ // get the canvas element that is the child of the div
71
+ const temporaryCanvas = getOrCreateCanvas(element);
64
72
  const renderingEngine =
65
73
  (getRenderingEngine(renderingEngineId) as RenderingEngine) ||
66
74
  new RenderingEngine(renderingEngineId);
@@ -73,6 +81,7 @@ export default function renderToCanvasGPU(
73
81
  type: ViewportType.STACK,
74
82
  element,
75
83
  defaultOptions: {
84
+ ...viewportOptions,
76
85
  suppressEvents: true,
77
86
  },
78
87
  };
@@ -91,9 +100,6 @@ export default function renderToCanvasGPU(
91
100
  return;
92
101
  }
93
102
 
94
- // get the canvas element that is the child of the div
95
- const temporaryCanvas = getOrCreateCanvas(element);
96
-
97
103
  // Copy the temporary canvas to the given canvas
98
104
  const context = canvas.getContext('2d');
99
105
  context.drawImage(
@@ -135,7 +141,7 @@ export default function renderToCanvasGPU(
135
141
  element.addEventListener(Events.IMAGE_RENDERED, onImageRendered);
136
142
  viewport.renderImageObject(image);
137
143
 
138
- // force a reset camera to center the image
144
+ // force a reset camera to center the image and undo the small scaling
139
145
  viewport.resetCamera();
140
146
 
141
147
  if (modality === 'PT' && !isPTPrescaledWithSUV(image)) {