@cornerstonejs/tools 1.71.7 → 1.72.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.
Files changed (67) hide show
  1. package/dist/cjs/index.d.ts +2 -2
  2. package/dist/cjs/index.js +3 -2
  3. package/dist/cjs/index.js.map +1 -1
  4. package/dist/cjs/tools/WindowLevelRegionTool.d.ts +26 -0
  5. package/dist/cjs/tools/WindowLevelRegionTool.js +228 -0
  6. package/dist/cjs/tools/WindowLevelRegionTool.js.map +1 -0
  7. package/dist/cjs/tools/index.d.ts +2 -1
  8. package/dist/cjs/tools/index.js +4 -2
  9. package/dist/cjs/tools/index.js.map +1 -1
  10. package/dist/cjs/utilities/voi/index.d.ts +2 -1
  11. package/dist/cjs/utilities/voi/index.js +3 -1
  12. package/dist/cjs/utilities/voi/index.js.map +1 -1
  13. package/dist/cjs/utilities/voi/windowlevel/calculateMinMaxMean.d.ts +6 -0
  14. package/dist/cjs/utilities/voi/windowlevel/calculateMinMaxMean.js +29 -0
  15. package/dist/cjs/utilities/voi/windowlevel/calculateMinMaxMean.js.map +1 -0
  16. package/dist/cjs/utilities/voi/windowlevel/extractWindowLevelRegionToolData.d.ts +11 -0
  17. package/dist/cjs/utilities/voi/windowlevel/extractWindowLevelRegionToolData.js +52 -0
  18. package/dist/cjs/utilities/voi/windowlevel/extractWindowLevelRegionToolData.js.map +1 -0
  19. package/dist/cjs/utilities/voi/windowlevel/getLuminanceFromRegion.d.ts +2 -0
  20. package/dist/cjs/utilities/voi/windowlevel/getLuminanceFromRegion.js +31 -0
  21. package/dist/cjs/utilities/voi/windowlevel/getLuminanceFromRegion.js.map +1 -0
  22. package/dist/cjs/utilities/voi/windowlevel/index.d.ts +4 -0
  23. package/dist/cjs/utilities/voi/windowlevel/index.js +10 -0
  24. package/dist/cjs/utilities/voi/windowlevel/index.js.map +1 -0
  25. package/dist/esm/index.js +2 -2
  26. package/dist/esm/index.js.map +1 -1
  27. package/dist/esm/tools/WindowLevelRegionTool.js +223 -0
  28. package/dist/esm/tools/WindowLevelRegionTool.js.map +1 -0
  29. package/dist/esm/tools/index.js +2 -1
  30. package/dist/esm/tools/index.js.map +1 -1
  31. package/dist/esm/utilities/voi/index.js +2 -1
  32. package/dist/esm/utilities/voi/index.js.map +1 -1
  33. package/dist/esm/utilities/voi/windowlevel/calculateMinMaxMean.js +26 -0
  34. package/dist/esm/utilities/voi/windowlevel/calculateMinMaxMean.js.map +1 -0
  35. package/dist/esm/utilities/voi/windowlevel/extractWindowLevelRegionToolData.js +49 -0
  36. package/dist/esm/utilities/voi/windowlevel/extractWindowLevelRegionToolData.js.map +1 -0
  37. package/dist/esm/utilities/voi/windowlevel/getLuminanceFromRegion.js +28 -0
  38. package/dist/esm/utilities/voi/windowlevel/getLuminanceFromRegion.js.map +1 -0
  39. package/dist/esm/utilities/voi/windowlevel/index.js +5 -0
  40. package/dist/esm/utilities/voi/windowlevel/index.js.map +1 -0
  41. package/dist/types/index.d.ts +2 -2
  42. package/dist/types/index.d.ts.map +1 -1
  43. package/dist/types/tools/WindowLevelRegionTool.d.ts +27 -0
  44. package/dist/types/tools/WindowLevelRegionTool.d.ts.map +1 -0
  45. package/dist/types/tools/index.d.ts +2 -1
  46. package/dist/types/tools/index.d.ts.map +1 -1
  47. package/dist/types/utilities/voi/index.d.ts +2 -1
  48. package/dist/types/utilities/voi/index.d.ts.map +1 -1
  49. package/dist/types/utilities/voi/windowlevel/calculateMinMaxMean.d.ts +7 -0
  50. package/dist/types/utilities/voi/windowlevel/calculateMinMaxMean.d.ts.map +1 -0
  51. package/dist/types/utilities/voi/windowlevel/extractWindowLevelRegionToolData.d.ts +12 -0
  52. package/dist/types/utilities/voi/windowlevel/extractWindowLevelRegionToolData.d.ts.map +1 -0
  53. package/dist/types/utilities/voi/windowlevel/getLuminanceFromRegion.d.ts +3 -0
  54. package/dist/types/utilities/voi/windowlevel/getLuminanceFromRegion.d.ts.map +1 -0
  55. package/dist/types/utilities/voi/windowlevel/index.d.ts +5 -0
  56. package/dist/types/utilities/voi/windowlevel/index.d.ts.map +1 -0
  57. package/dist/umd/index.js +1 -1
  58. package/dist/umd/index.js.map +1 -1
  59. package/package.json +3 -3
  60. package/src/index.ts +2 -0
  61. package/src/tools/WindowLevelRegionTool.ts +399 -0
  62. package/src/tools/index.ts +2 -0
  63. package/src/utilities/voi/index.ts +2 -1
  64. package/src/utilities/voi/windowlevel/calculateMinMaxMean.ts +30 -0
  65. package/src/utilities/voi/windowlevel/extractWindowLevelRegionToolData.ts +63 -0
  66. package/src/utilities/voi/windowlevel/getLuminanceFromRegion.ts +43 -0
  67. package/src/utilities/voi/windowlevel/index.ts +9 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cornerstonejs/tools",
3
- "version": "1.71.7",
3
+ "version": "1.72.1",
4
4
  "description": "Cornerstone3D Tools",
5
5
  "main": "src/index.ts",
6
6
  "types": "dist/types/index.d.ts",
@@ -29,7 +29,7 @@
29
29
  "webpack:watch": "webpack --mode development --progress --watch --config ./.webpack/webpack.dev.js"
30
30
  },
31
31
  "dependencies": {
32
- "@cornerstonejs/core": "^1.71.7",
32
+ "@cornerstonejs/core": "^1.72.1",
33
33
  "@icr/polyseg-wasm": "0.4.0",
34
34
  "@types/offscreencanvas": "2019.7.3",
35
35
  "comlink": "^4.4.1",
@@ -59,5 +59,5 @@
59
59
  "type": "individual",
60
60
  "url": "https://ohif.org/donate"
61
61
  },
62
- "gitHead": "ad670a9725df1bea99ba901c3b24736c3c1926e9"
62
+ "gitHead": "8ae23a54d44a169da137795244394e79389437f6"
63
63
  }
package/src/index.ts CHANGED
@@ -73,6 +73,7 @@ import {
73
73
  EraserTool,
74
74
  SculptorTool,
75
75
  SegmentSelectTool,
76
+ WindowLevelRegionTool,
76
77
  } from './tools';
77
78
 
78
79
  import VideoRedactionTool from './tools/annotation/VideoRedactionTool';
@@ -96,6 +97,7 @@ export {
96
97
  TrackballRotateTool,
97
98
  DragProbeTool,
98
99
  WindowLevelTool,
100
+ WindowLevelRegionTool,
99
101
  ZoomTool,
100
102
  StackScrollTool,
101
103
  PlanarRotateTool,
@@ -0,0 +1,399 @@
1
+ import { AnnotationTool } from './base';
2
+
3
+ import { getEnabledElement, utilities } from '@cornerstonejs/core';
4
+ import type { Types } from '@cornerstonejs/core';
5
+ import {
6
+ addAnnotation,
7
+ getAnnotations,
8
+ removeAnnotation,
9
+ } from '../stateManagement';
10
+ import { triggerAnnotationCompleted } from '../stateManagement/annotation/helpers/state';
11
+ import { drawRect as drawRectSvg } from '../drawingSvg';
12
+ import { state } from '../store';
13
+ import { Events } from '../enums';
14
+ import { getViewportIdsWithToolToRender } from '../utilities/viewportFilters';
15
+ import {
16
+ resetElementCursor,
17
+ hideElementCursor,
18
+ } from '../cursors/elementCursor';
19
+ import triggerAnnotationRenderForViewportIds from '../utilities/triggerAnnotationRenderForViewportIds';
20
+
21
+ import {
22
+ EventTypes,
23
+ ToolProps,
24
+ PublicToolProps,
25
+ SVGDrawingHelper,
26
+ } from '../types';
27
+ import { RectangleROIAnnotation } from '../types/ToolSpecificAnnotationTypes';
28
+ import { StyleSpecifier } from '../types/AnnotationStyle';
29
+
30
+ import { windowLevel } from '../utilities/voi';
31
+
32
+ import { clip } from '../utilities';
33
+
34
+ /**
35
+ * WindowLevelRegion tool manipulates the windowLevel applied to a viewport. It
36
+ * provides a way to set the windowCenter and windowWidth of a viewport
37
+ * by dragging mouse over the image to draw a rectangle region which is used to calculate
38
+ * the windowCenter and windowWidth based on the ROI
39
+ *
40
+ */
41
+
42
+ class WindowLevelRegionTool extends AnnotationTool {
43
+ static toolName;
44
+
45
+ editData: {
46
+ annotation: any;
47
+ viewportIdsToRender: string[];
48
+ } | null;
49
+ isDrawing: boolean;
50
+
51
+ constructor(
52
+ toolProps: PublicToolProps = {},
53
+ defaultToolProps: ToolProps = {
54
+ supportedInteractionTypes: ['Mouse', 'Touch'],
55
+ configuration: {
56
+ // The minimum window width to be applied to the viewport regardless of the calculated value
57
+ minWindowWidth: 10,
58
+ },
59
+ }
60
+ ) {
61
+ super(toolProps, defaultToolProps);
62
+ }
63
+
64
+ /**
65
+ * Based on the current position of the mouse and the current imageId to create
66
+ * a RectangleROI Annotation and stores it in the annotationManager
67
+ *
68
+ * @param evt - EventTypes.NormalizedMouseEventType
69
+ * @returns The annotation object.
70
+ *
71
+ */
72
+ addNewAnnotation = (evt: EventTypes.InteractionEventType): any => {
73
+ const eventDetail = evt.detail;
74
+ const { currentPoints, element } = eventDetail;
75
+ const worldPos = currentPoints.world;
76
+
77
+ const enabledElement = getEnabledElement(element);
78
+ const { viewport, renderingEngine } = enabledElement;
79
+
80
+ this.isDrawing = true;
81
+
82
+ const camera = viewport.getCamera();
83
+ const { viewPlaneNormal, viewUp } = camera;
84
+
85
+ const referencedImageId = this.getReferencedImageId(
86
+ viewport,
87
+ worldPos,
88
+ viewPlaneNormal,
89
+ viewUp
90
+ );
91
+
92
+ const FrameOfReferenceUID = viewport.getFrameOfReferenceUID();
93
+
94
+ const annotation = {
95
+ invalidated: true,
96
+ highlighted: true,
97
+ metadata: {
98
+ toolName: this.getToolName(),
99
+ viewPlaneNormal: <Types.Point3>[...viewPlaneNormal],
100
+ viewUp: <Types.Point3>[...viewUp],
101
+ FrameOfReferenceUID,
102
+ referencedImageId,
103
+ },
104
+ data: {
105
+ handles: {
106
+ points: [
107
+ <Types.Point3>[...worldPos],
108
+ <Types.Point3>[...worldPos],
109
+ <Types.Point3>[...worldPos],
110
+ <Types.Point3>[...worldPos],
111
+ ],
112
+ },
113
+ cachedStats: {},
114
+ },
115
+ };
116
+
117
+ addAnnotation(annotation, element);
118
+
119
+ const viewportIdsToRender = getViewportIdsWithToolToRender(
120
+ element,
121
+ this.getToolName()
122
+ );
123
+
124
+ this.editData = {
125
+ annotation,
126
+ viewportIdsToRender,
127
+ };
128
+ this._activateDraw(element);
129
+
130
+ hideElementCursor(element);
131
+
132
+ evt.preventDefault();
133
+
134
+ triggerAnnotationRenderForViewportIds(renderingEngine, viewportIdsToRender);
135
+
136
+ return annotation;
137
+ };
138
+
139
+ _endCallback = (evt: EventTypes.InteractionEventType): void => {
140
+ const eventDetail = evt.detail;
141
+ const { element } = eventDetail;
142
+
143
+ const { annotation, viewportIdsToRender } = this.editData;
144
+
145
+ this._deactivateDraw(element);
146
+
147
+ resetElementCursor(element);
148
+
149
+ const { renderingEngine } = getEnabledElement(element);
150
+
151
+ this.editData = null;
152
+ this.isDrawing = false;
153
+
154
+ removeAnnotation(annotation.annotationUID);
155
+
156
+ triggerAnnotationRenderForViewportIds(renderingEngine, viewportIdsToRender);
157
+
158
+ triggerAnnotationCompleted(annotation);
159
+
160
+ this.applyWindowLevelRegion(annotation, element);
161
+ };
162
+
163
+ _dragCallback = (evt: EventTypes.InteractionEventType): void => {
164
+ this.isDrawing = true;
165
+
166
+ const eventDetail = evt.detail;
167
+ const { element } = eventDetail;
168
+
169
+ const { annotation, viewportIdsToRender } = this.editData;
170
+ const { data } = annotation;
171
+ const { currentPoints } = eventDetail;
172
+ const enabledElement = getEnabledElement(element);
173
+ const { worldToCanvas, canvasToWorld } = enabledElement.viewport;
174
+ const worldPos = currentPoints.world;
175
+
176
+ const { points } = data.handles;
177
+ const DEFAULT_HANDLE_INDEX = 3;
178
+ points[DEFAULT_HANDLE_INDEX] = [...worldPos];
179
+
180
+ const bottomLeftCanvas = worldToCanvas(points[0]);
181
+ const topRightCanvas = worldToCanvas(points[3]);
182
+
183
+ const bottomRightCanvas = <Types.Point2>[
184
+ topRightCanvas[0],
185
+ bottomLeftCanvas[1],
186
+ ];
187
+ const topLeftCanvas = <Types.Point2>[
188
+ bottomLeftCanvas[0],
189
+ topRightCanvas[1],
190
+ ];
191
+
192
+ const bottomRightWorld = canvasToWorld(bottomRightCanvas);
193
+ const topLeftWorld = canvasToWorld(topLeftCanvas);
194
+
195
+ points[1] = bottomRightWorld;
196
+ points[2] = topLeftWorld;
197
+
198
+ annotation.invalidated = true;
199
+
200
+ const { renderingEngine } = enabledElement;
201
+
202
+ triggerAnnotationRenderForViewportIds(renderingEngine, viewportIdsToRender);
203
+ };
204
+
205
+ /**
206
+ * Add event handlers for the modify event loop, and prevent default event prapogation.
207
+ */
208
+ _activateDraw = (element) => {
209
+ state.isInteractingWithTool = true;
210
+
211
+ element.addEventListener(Events.MOUSE_UP, this._endCallback);
212
+ element.addEventListener(Events.MOUSE_DRAG, this._dragCallback);
213
+ element.addEventListener(Events.MOUSE_MOVE, this._dragCallback);
214
+ element.addEventListener(Events.MOUSE_CLICK, this._endCallback);
215
+
216
+ element.addEventListener(Events.TOUCH_END, this._endCallback);
217
+ element.addEventListener(Events.TOUCH_DRAG, this._dragCallback);
218
+ element.addEventListener(Events.TOUCH_TAP, this._endCallback);
219
+ };
220
+
221
+ /**
222
+ * Add event handlers for the modify event loop, and prevent default event prapogation.
223
+ */
224
+ _deactivateDraw = (element) => {
225
+ state.isInteractingWithTool = false;
226
+
227
+ element.removeEventListener(Events.MOUSE_UP, this._endCallback);
228
+ element.removeEventListener(Events.MOUSE_DRAG, this._dragCallback);
229
+ element.removeEventListener(Events.MOUSE_MOVE, this._dragCallback);
230
+ element.removeEventListener(Events.MOUSE_CLICK, this._endCallback);
231
+
232
+ element.removeEventListener(Events.TOUCH_END, this._endCallback);
233
+ element.removeEventListener(Events.TOUCH_DRAG, this._dragCallback);
234
+ element.removeEventListener(Events.TOUCH_TAP, this._endCallback);
235
+ };
236
+
237
+ /**
238
+ * it is used to draw the rectangleROI annotation in each
239
+ * request animation frame. It calculates the updated cached statistics if
240
+ * data is invalidated and cache it.
241
+ *
242
+ * @param enabledElement - The Cornerstone's enabledElement.
243
+ * @param svgDrawingHelper - The svgDrawingHelper providing the context for drawing.
244
+ */
245
+ renderAnnotation = (
246
+ enabledElement: Types.IEnabledElement,
247
+ svgDrawingHelper: SVGDrawingHelper
248
+ ): boolean => {
249
+ let renderStatus = false;
250
+ const { viewport } = enabledElement;
251
+ const { element } = viewport;
252
+
253
+ let annotations = getAnnotations(this.getToolName(), element);
254
+
255
+ if (!annotations?.length) {
256
+ return renderStatus;
257
+ }
258
+
259
+ annotations = this.filterInteractableAnnotationsForElement(
260
+ element,
261
+ annotations
262
+ );
263
+
264
+ if (!annotations?.length) {
265
+ return renderStatus;
266
+ }
267
+
268
+ const styleSpecifier: StyleSpecifier = {
269
+ toolGroupId: this.toolGroupId,
270
+ toolName: this.getToolName(),
271
+ viewportId: enabledElement.viewport.id,
272
+ };
273
+
274
+ for (let i = 0; i < annotations.length; i++) {
275
+ const annotation = annotations[i] as RectangleROIAnnotation;
276
+ const { annotationUID, data } = annotation;
277
+ const { points } = data.handles;
278
+
279
+ const canvasCoordinates = points.map((p) => viewport.worldToCanvas(p));
280
+
281
+ styleSpecifier.annotationUID = annotationUID;
282
+
283
+ const { color, lineWidth, lineDash } = this.getAnnotationStyle({
284
+ annotation,
285
+ styleSpecifier,
286
+ });
287
+
288
+ // If rendering engine has been destroyed while rendering
289
+ if (!viewport.getRenderingEngine()) {
290
+ console.warn('Rendering Engine has been destroyed');
291
+ return renderStatus;
292
+ }
293
+
294
+ const dataId = `${annotationUID}-rect`;
295
+ const rectangleUID = '0';
296
+ drawRectSvg(
297
+ svgDrawingHelper,
298
+ annotationUID,
299
+ rectangleUID,
300
+ canvasCoordinates[0],
301
+ canvasCoordinates[3],
302
+ {
303
+ color,
304
+ lineDash,
305
+ lineWidth,
306
+ },
307
+ dataId
308
+ );
309
+
310
+ renderStatus = true;
311
+ }
312
+
313
+ return renderStatus;
314
+ };
315
+
316
+ applyWindowLevelRegion = (annotation, element): void => {
317
+ const enabledElement = getEnabledElement(element);
318
+ const { viewport } = enabledElement;
319
+ const imageData = windowLevel.extractWindowLevelRegionToolData(viewport);
320
+ const { data } = annotation;
321
+ const { points } = data.handles;
322
+
323
+ const canvasCoordinates = points.map((p) => viewport.worldToCanvas(p));
324
+ const startCanvas = canvasCoordinates[0];
325
+ const endCanvas = canvasCoordinates[3];
326
+
327
+ let left = Math.min(startCanvas[0], endCanvas[0]);
328
+ let top = Math.min(startCanvas[1], endCanvas[1]);
329
+ let width = Math.abs(startCanvas[0] - endCanvas[0]);
330
+ let height = Math.abs(startCanvas[1] - endCanvas[1]);
331
+
332
+ left = clip(left, 0, imageData.width);
333
+ top = clip(top, 0, imageData.height);
334
+ width = Math.floor(Math.min(width, Math.abs(imageData.width - left)));
335
+ height = Math.floor(Math.min(height, Math.abs(imageData.height - top)));
336
+
337
+ // Get the pixel data in the rectangular region
338
+ const pixelLuminanceData = windowLevel.getLuminanceFromRegion(
339
+ imageData,
340
+ Math.round(left),
341
+ Math.round(top),
342
+ width,
343
+ height
344
+ );
345
+
346
+ // Calculate the minimum and maximum pixel values
347
+ const minMaxMean = windowLevel.calculateMinMaxMean(
348
+ pixelLuminanceData,
349
+ imageData.minPixelValue,
350
+ imageData.maxPixelValue
351
+ );
352
+
353
+ // Adjust the viewport window width and center based on the calculated values
354
+ if (this.configuration.minWindowWidth === undefined) {
355
+ this.configuration.minWindowWidth = 10;
356
+ }
357
+
358
+ const windowWidth = Math.max(
359
+ Math.abs(minMaxMean.max - minMaxMean.min),
360
+ this.configuration.minWindowWidth
361
+ );
362
+ const windowCenter = minMaxMean.mean;
363
+
364
+ const voiRange = utilities.windowLevel.toLowHighRange(
365
+ windowWidth,
366
+ windowCenter
367
+ );
368
+
369
+ viewport.setProperties({ voiRange });
370
+ viewport.render();
371
+ };
372
+
373
+ cancel = (): void => {
374
+ return null;
375
+ };
376
+
377
+ isPointNearTool = () => {
378
+ return null;
379
+ };
380
+
381
+ toolSelectedCallback = (): void => {
382
+ return null;
383
+ };
384
+
385
+ handleSelectedCallback = (): void => {
386
+ return null;
387
+ };
388
+
389
+ _activateModify = (): void => {
390
+ return null;
391
+ };
392
+
393
+ _deactivateModify = (): void => {
394
+ return null;
395
+ };
396
+ }
397
+
398
+ WindowLevelRegionTool.toolName = 'WindowLevelRegion';
399
+ export default WindowLevelRegionTool;
@@ -2,6 +2,7 @@ import { BaseTool, AnnotationTool, AnnotationDisplayTool } from './base';
2
2
  import PanTool from './PanTool';
3
3
  import TrackballRotateTool from './TrackballRotateTool';
4
4
  import WindowLevelTool from './WindowLevelTool';
5
+ import WindowLevelRegionTool from './WindowLevelRegionTool';
5
6
  import StackScrollTool from './StackScrollTool';
6
7
  import PlanarRotateTool from './PlanarRotateTool';
7
8
  import StackScrollMouseWheelTool from './StackScrollToolMouseWheelTool';
@@ -65,6 +66,7 @@ export {
65
66
  TrackballRotateTool,
66
67
  DragProbeTool,
67
68
  WindowLevelTool,
69
+ WindowLevelRegionTool,
68
70
  StackScrollTool,
69
71
  PlanarRotateTool,
70
72
  StackScrollMouseWheelTool,
@@ -1,3 +1,4 @@
1
1
  import * as colorbar from './colorbar';
2
+ import * as windowLevel from './windowlevel';
2
3
 
3
- export { colorbar };
4
+ export { colorbar, windowLevel };
@@ -0,0 +1,30 @@
1
+ function calculateMinMaxMean(pixelLuminance, globalMin, globalMax) {
2
+ const numPixels = pixelLuminance.length;
3
+ let min = globalMax;
4
+ let max = globalMin;
5
+ let sum = 0;
6
+
7
+ if (numPixels < 2) {
8
+ return {
9
+ min,
10
+ max,
11
+ mean: (globalMin + globalMax) / 2,
12
+ };
13
+ }
14
+
15
+ for (let index = 0; index < numPixels; index++) {
16
+ const spv = pixelLuminance[index];
17
+
18
+ min = Math.min(min, spv);
19
+ max = Math.max(max, spv);
20
+ sum += spv;
21
+ }
22
+
23
+ return {
24
+ min,
25
+ max,
26
+ mean: sum / numPixels,
27
+ };
28
+ }
29
+
30
+ export { calculateMinMaxMean };
@@ -0,0 +1,63 @@
1
+ import {
2
+ VolumeViewport,
3
+ utilities as csUtils,
4
+ cache,
5
+ StackViewport,
6
+ } from '@cornerstonejs/core';
7
+
8
+ function extractWindowLevelRegionToolData(viewport) {
9
+ if (viewport instanceof VolumeViewport) {
10
+ return extractImageDataVolume(viewport);
11
+ }
12
+ if (viewport instanceof StackViewport) {
13
+ return extractImageDataStack(viewport);
14
+ }
15
+
16
+ throw new Error('Viewport not supported');
17
+ }
18
+
19
+ function extractImageDataVolume(viewport) {
20
+ const { scalarData, width, height } =
21
+ csUtils.getCurrentVolumeViewportSlice(viewport);
22
+ const { min: minPixelValue, max: maxPixelValue } =
23
+ csUtils.getMinMax(scalarData);
24
+ const volumeId = viewport.getVolumeId();
25
+ const volume = cache.getVolume(volumeId);
26
+ // @ts-ignore
27
+ const { metadata, cornerstoneImageMetaData } = volume;
28
+ const { Rows: rows, Columns: columns } = metadata;
29
+ const { color } = cornerstoneImageMetaData;
30
+ return {
31
+ scalarData,
32
+ width,
33
+ height,
34
+ minPixelValue,
35
+ maxPixelValue,
36
+ rows,
37
+ columns,
38
+ color,
39
+ };
40
+ }
41
+
42
+ function extractImageDataStack(viewport) {
43
+ const imageData = viewport.getImageData();
44
+ const { scalarData } = imageData;
45
+ const { min: minPixelValue, max: maxPixelValue } =
46
+ csUtils.getMinMax(scalarData);
47
+ const width = imageData.dimensions[0];
48
+ const height = imageData.dimensions[1];
49
+ const { rows, columns, color } = viewport.getCornerstoneImage();
50
+
51
+ return {
52
+ scalarData,
53
+ width,
54
+ height,
55
+ minPixelValue,
56
+ maxPixelValue,
57
+ rows,
58
+ columns,
59
+ color,
60
+ };
61
+ }
62
+
63
+ export { extractWindowLevelRegionToolData };
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Extracts the luminance values from a specified region of an image.
3
+ *
4
+ * @param {Object} imageData - The image data object containing pixel information.
5
+ * @param {Uint8Array} imageData.scalarData - The pixel data array.
6
+ * @param {boolean} imageData.color - A flag indicating if the image is in color (true) or grayscale (false).
7
+ * @param {number} imageData.columns - The number of columns (width) in the image.
8
+ * @param {number} x - The x-coordinate of the top-left corner of the region.
9
+ * @param {number} y - The y-coordinate of the top-left corner of the region.
10
+ * @param {number} width - The width of the region.
11
+ * @param {number} height - The height of the region.
12
+ * @returns {number[]} An array containing the luminance values of the specified region.
13
+ */
14
+ function getLuminanceFromRegion(imageData, x, y, width, height) {
15
+ const luminance = [];
16
+ let index = 0;
17
+ const pixelData = imageData.scalarData;
18
+ let spIndex, row, column;
19
+
20
+ if (imageData.color) {
21
+ for (row = 0; row < height; row++) {
22
+ for (column = 0; column < width; column++) {
23
+ spIndex = ((row + y) * imageData.columns + (column + x)) * 4;
24
+ const red = pixelData[spIndex];
25
+ const green = pixelData[spIndex + 1];
26
+ const blue = pixelData[spIndex + 2];
27
+
28
+ luminance[index++] = 0.2126 * red + 0.7152 * green + 0.0722 * blue;
29
+ }
30
+ }
31
+ } else {
32
+ for (row = 0; row < height; row++) {
33
+ for (column = 0; column < width; column++) {
34
+ spIndex = (row + y) * imageData.columns + (column + x);
35
+ luminance[index++] = pixelData[spIndex];
36
+ }
37
+ }
38
+ }
39
+
40
+ return luminance;
41
+ }
42
+
43
+ export { getLuminanceFromRegion };
@@ -0,0 +1,9 @@
1
+ import { getLuminanceFromRegion } from './getLuminanceFromRegion';
2
+ import { calculateMinMaxMean } from './calculateMinMaxMean';
3
+ import { extractWindowLevelRegionToolData } from './extractWindowLevelRegionToolData';
4
+
5
+ export {
6
+ getLuminanceFromRegion,
7
+ calculateMinMaxMean,
8
+ extractWindowLevelRegionToolData,
9
+ };