larvitar 1.5.14 → 2.0.2

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 (107) hide show
  1. package/.vscode/settings.json +4 -0
  2. package/README.md +78 -48
  3. package/bundler/webpack.common.js +27 -0
  4. package/bundler/webpack.dev.js +23 -0
  5. package/bundler/webpack.prod.js +19 -0
  6. package/decs.d.ts +12 -0
  7. package/dist/imaging/MetaDataReadable.d.ts +40 -0
  8. package/dist/imaging/MetaDataTypes.d.ts +3489 -0
  9. package/dist/imaging/imageAnonymization.d.ts +12 -0
  10. package/dist/imaging/imageColormaps.d.ts +47 -0
  11. package/dist/imaging/imageContours.d.ts +18 -0
  12. package/dist/imaging/imageIo.d.ts +42 -0
  13. package/dist/imaging/imageLayers.d.ts +56 -0
  14. package/dist/imaging/imageLoading.d.ts +65 -0
  15. package/dist/imaging/imageParsing.d.ts +46 -0
  16. package/dist/imaging/imagePresets.d.ts +43 -0
  17. package/dist/imaging/imageRendering.d.ts +238 -0
  18. package/dist/imaging/imageReslice.d.ts +14 -0
  19. package/dist/imaging/imageStore.d.ts +121 -0
  20. package/dist/imaging/imageTags.d.ts +22 -0
  21. package/dist/imaging/imageTools.d.ts +20 -0
  22. package/dist/imaging/imageUtils.d.ts +165 -0
  23. package/dist/imaging/loaders/commonLoader.d.ts +103 -0
  24. package/dist/imaging/loaders/dicomLoader.d.ts +29 -0
  25. package/dist/imaging/loaders/fileLoader.d.ts +33 -0
  26. package/dist/imaging/loaders/multiframeLoader.d.ts +37 -0
  27. package/dist/imaging/loaders/nrrdLoader.d.ts +113 -0
  28. package/dist/imaging/loaders/resliceLoader.d.ts +15 -0
  29. package/dist/imaging/monitors/memory.d.ts +41 -0
  30. package/dist/imaging/monitors/performance.d.ts +23 -0
  31. package/dist/imaging/parsers/ecg.d.ts +15 -0
  32. package/dist/imaging/parsers/nrrd.d.ts +3 -0
  33. package/dist/imaging/tools/custom/4dSliceScrollTool.d.ts +12 -0
  34. package/dist/imaging/tools/custom/BorderMagnifyTool.d.ts +18 -0
  35. package/dist/imaging/tools/custom/contourTool.d.ts +409 -0
  36. package/dist/imaging/tools/custom/diameterTool.d.ts +18 -0
  37. package/dist/imaging/tools/custom/editMaskTool.d.ts +22 -0
  38. package/dist/imaging/tools/custom/ellipticalRoiOverlayTool.d.ts +45 -0
  39. package/dist/imaging/tools/custom/polygonSegmentationMixin.d.ts +54 -0
  40. package/dist/imaging/tools/custom/polylineScissorsTool.d.ts +11 -0
  41. package/dist/imaging/tools/custom/rectangleRoiOverlayTool.d.ts +45 -0
  42. package/dist/imaging/tools/custom/seedTool.d.ts +0 -0
  43. package/dist/imaging/tools/custom/setLabelMap3D.d.ts +39 -0
  44. package/dist/imaging/tools/custom/thresholdsBrushTool.d.ts +19 -0
  45. package/dist/imaging/tools/default.d.ts +53 -0
  46. package/dist/imaging/tools/interaction.d.ts +30 -0
  47. package/dist/imaging/tools/io.d.ts +38 -0
  48. package/dist/imaging/tools/main.d.ts +81 -0
  49. package/dist/imaging/tools/segmentation.d.ts +125 -0
  50. package/dist/imaging/tools/state.d.ts +17 -0
  51. package/dist/imaging/tools/strategies/eraseFreehand.d.ts +16 -0
  52. package/dist/imaging/tools/strategies/fillFreehand.d.ts +16 -0
  53. package/dist/imaging/tools/strategies/index.d.ts +2 -0
  54. package/dist/imaging/waveforms/ecg.d.ts +39 -0
  55. package/dist/index.d.ts +35 -0
  56. package/dist/larvitar.js +90104 -0
  57. package/dist/larvitar.js.map +1 -0
  58. package/imaging/MetaDataReadable.ts +41 -0
  59. package/imaging/MetaDataTypes.ts +3491 -0
  60. package/imaging/dataDictionary.json +5328 -5328
  61. package/imaging/{imageAnonymization.js → imageAnonymization.ts} +41 -13
  62. package/imaging/{imageColormaps.js → imageColormaps.ts} +48 -30
  63. package/imaging/{imageContours.js → imageContours.ts} +24 -22
  64. package/imaging/{imageIo.js → imageIo.ts} +89 -52
  65. package/imaging/{imageLayers.js → imageLayers.ts} +31 -14
  66. package/imaging/{imageLoading.js → imageLoading.ts} +107 -43
  67. package/imaging/{imageParsing.js → imageParsing.ts} +160 -80
  68. package/imaging/{imagePresets.js → imagePresets.ts} +44 -11
  69. package/imaging/imageRendering.ts +1091 -0
  70. package/imaging/{imageReslice.js → imageReslice.ts} +18 -9
  71. package/imaging/imageStore.ts +487 -0
  72. package/imaging/imageTags.ts +609 -0
  73. package/imaging/imageTools.js +2 -1
  74. package/imaging/{imageUtils.js → imageUtils.ts} +211 -701
  75. package/imaging/loaders/{commonLoader.js → commonLoader.ts} +73 -24
  76. package/imaging/loaders/{dicomLoader.js → dicomLoader.ts} +25 -5
  77. package/imaging/loaders/{fileLoader.js → fileLoader.ts} +5 -5
  78. package/imaging/loaders/{multiframeLoader.js → multiframeLoader.ts} +145 -90
  79. package/imaging/loaders/{nrrdLoader.js → nrrdLoader.ts} +231 -64
  80. package/imaging/loaders/{resliceLoader.js → resliceLoader.ts} +51 -20
  81. package/imaging/monitors/{memory.js → memory.ts} +54 -8
  82. package/imaging/monitors/performance.ts +34 -0
  83. package/imaging/parsers/ecg.ts +54 -0
  84. package/imaging/tools/README.md +27 -0
  85. package/imaging/tools/custom/4dSliceScrollTool.js +47 -46
  86. package/imaging/tools/custom/BorderMagnifyTool.js +99 -0
  87. package/imaging/tools/custom/ellipticalRoiOverlayTool.js +534 -0
  88. package/imaging/tools/custom/polylineScissorsTool.js +1 -1
  89. package/imaging/tools/custom/rectangleRoiOverlayTool.js +564 -0
  90. package/imaging/tools/{setLabelMap3D.js → custom/setLabelMap3D.ts} +19 -25
  91. package/imaging/tools/{default.js → default.ts} +119 -33
  92. package/imaging/tools/{interaction.js → interaction.ts} +42 -23
  93. package/imaging/tools/{io.js → io.ts} +47 -31
  94. package/imaging/tools/{main.js → main.ts} +105 -40
  95. package/imaging/tools/{segmentation.js → segmentation.ts} +95 -68
  96. package/imaging/tools/{state.js → state.ts} +7 -12
  97. package/imaging/tools/types.d.ts +243 -0
  98. package/imaging/types.d.ts +200 -0
  99. package/imaging/waveforms/ecg.ts +191 -0
  100. package/{index.js → index.ts} +53 -14
  101. package/jsdoc.json +1 -1
  102. package/package.json +35 -14
  103. package/tsconfig.json +102 -0
  104. package/imaging/imageRendering.js +0 -860
  105. package/imaging/imageStore.js +0 -322
  106. package/modules/vuex/larvitar.js +0 -187
  107. /package/imaging/tools/{polygonSegmentationMixin.js → custom/polygonSegmentationMixin.js} +0 -0
@@ -1,860 +0,0 @@
1
- /** @module imaging/imageRendering
2
- * @desc This file provides functionalities for
3
- * rendering images in html canvas using cornerstone
4
- */
5
-
6
- // external libraries
7
- import cornerstone from "cornerstone-core";
8
- import { default as cornerstoneDICOMImageLoader } from "cornerstone-wado-image-loader";
9
- import { each, has } from "lodash";
10
-
11
- // internal libraries
12
- import { getFileImageId } from "./loaders/fileLoader";
13
- import { csToolsCreateStack } from "./tools/main";
14
- import { toggleMouseToolsListeners } from "./tools/interaction";
15
- import { larvitar_store } from "./imageStore";
16
- import { applyColorMap } from "./imageColormaps";
17
- import { isElement } from "./imageUtils";
18
-
19
- /*
20
- * This module provides the following functions to be exported:
21
- * clearImageCache(seriesId)
22
- * loadAndCacheImages(seriesData)
23
- * renderFileImage(file, elementId)
24
- * renderWebImage(url, elementId)
25
- * disableViewport(elementId)
26
- * unloadViewport(elementId, seriesId)
27
- * resizeViewport(elementId)
28
- * renderImage(series, elementId, defaultProps)
29
- * updateImage(series, elementId, imageIndex)
30
- * resetViewports([elementIds])
31
- * updateViewportData(elementId)
32
- * toggleMouseHandlers(elementId, disableFlag)
33
- * storeViewportData(params...)
34
- * invertImage(elementId)
35
- * flipImageHorizontal(elementId)
36
- * flipImageVertical(elementId)
37
- * rotateImageLeft(elementId)
38
- * rotateImageRight(elementId)
39
- */
40
-
41
- /**
42
- * Purge the cornestone internal cache
43
- * If seriesId is passed as argument only imageIds of the series are purged from internal cache
44
- * @instance
45
- * @function clearImageCache
46
- * @param {String} seriesId - The id of the serie
47
- */
48
- export const clearImageCache = function (seriesId) {
49
- if (seriesId) {
50
- let series = larvitar_store.get("series");
51
- if (has(series, seriesId)) {
52
- each(series[seriesId].imageIds, function (imageId) {
53
- if (cornerstone.imageCache.cachedImages.length > 0) {
54
- try {
55
- cornerstone.imageCache.removeImageLoadObject(imageId);
56
- } catch (e) {
57
- console.warn("no cached image");
58
- }
59
- } else {
60
- let uri =
61
- cornerstoneDICOMImageLoader.wadouri.parseImageId(imageId).url;
62
- cornerstoneDICOMImageLoader.wadouri.dataSetCacheManager.unload(uri);
63
- }
64
- });
65
-
66
- larvitar_store.removeSeriesIds(seriesId);
67
- console.log("Uncached images for ", seriesId);
68
- }
69
- } else {
70
- cornerstone.imageCache.purgeCache();
71
- }
72
- };
73
-
74
- /**
75
- * Load and cache all serie's images
76
- * Add series's imageIds into store
77
- * @instance
78
- * @function loadAndCacheImages
79
- * @param {Object} series the parsed series data
80
- * @param {Function} callback a callback function
81
- */
82
- export function loadAndCacheImages(series, callback) {
83
- let t0 = performance.now();
84
- let cachingCounter = 0;
85
- if (series.isMultiframe) {
86
- // console.warn("Do not cache multiframe images for performance issues");
87
- return;
88
- }
89
- let response = {
90
- seriesId: series.seriesUID,
91
- loading: 0,
92
- series: {}
93
- };
94
- callback(response);
95
- // add serie's imageIds into store
96
- larvitar_store.addSeriesIds(series.seriesUID, series.imageIds);
97
- // add serie's caching progress into store
98
- larvitar_store.set("progress", [series.seriesUID, 0]);
99
- each(series.imageIds, function (imageId) {
100
- cornerstone.loadAndCacheImage(imageId).then(function () {
101
- cachingCounter += 1;
102
- let cachingPercentage = Math.floor(
103
- (cachingCounter / series.imageIds.length) * 100
104
- );
105
- response.loading = cachingPercentage;
106
- larvitar_store.set("progress", [series.seriesUID, cachingPercentage]);
107
- if (cachingCounter == series.imageIds.length) {
108
- let t1 = performance.now();
109
- console.log(`Call to cacheImages took ${t1 - t0} milliseconds.`);
110
- console.log("Cached images for ", series.seriesUID);
111
- response.series = series;
112
- }
113
- callback(response);
114
- });
115
- });
116
- }
117
-
118
- /**
119
- * Render a PDF from a DICOM Encapsulated PDF
120
- * @instance
121
- * @function renderDICOMPDF
122
- * @param {Object} seriesStack - The original series data object
123
- * @param {String} elementId - The html div id used for rendering or its DOM HTMLElement
124
- * @returns {Promise} - Return a promise which will resolve when pdf is displayed
125
- */
126
- export const renderDICOMPDF = function (seriesStack, elementId) {
127
- let t0 = performance.now();
128
- let element = isElement(elementId)
129
- ? elementId
130
- : document.getElementById(elementId);
131
- if (!element) {
132
- console.error("invalid html element: " + elementId);
133
- return;
134
- }
135
- let renderPromise = new Promise((resolve, reject) => {
136
- let image = seriesStack.instances[seriesStack.imageIds[0]];
137
- const SOPUID = image.dataSet.string("x00080016");
138
- if (SOPUID === "1.2.840.10008.5.1.4.1.1.104.1") {
139
- let fileTag = image.dataSet.elements.x00420011;
140
- let pdfByteArray = image.dataSet.byteArray.slice(
141
- fileTag.dataOffset,
142
- fileTag.dataOffset + fileTag.length
143
- );
144
- let PDF = new Blob([pdfByteArray], { type: "application/pdf" });
145
- let fileURL = URL.createObjectURL(PDF);
146
- element.innerHTML =
147
- '<object data="' +
148
- fileURL +
149
- '" type="application/pdf" width="100%" height="100%"></object>';
150
- larvitar_store.set("isPDF", [elementId, true]);
151
- let t1 = performance.now();
152
- console.log(`Call to renderDICOMPDF took ${t1 - t0} milliseconds.`);
153
- image = null;
154
- fileTag = null;
155
- pdfByteArray = null;
156
- PDF = null;
157
- fileURL = null;
158
- resolve();
159
- } else {
160
- reject("This is not a DICOM with a PDF");
161
- }
162
- });
163
- return renderPromise;
164
- };
165
-
166
- /**
167
- * Render an image (png or jpg) from File on a html div using cornerstone
168
- * @instance
169
- * @function renderWebImage
170
- * @param {Object} file - The image File object
171
- * @param {String} elementId - The html div id used for rendering or its DOM HTMLElement
172
- * @returns {Promise} - Return a promise which will resolve when image is displayed
173
- */
174
- export const renderFileImage = function (file, elementId) {
175
- let element = isElement(elementId)
176
- ? elementId
177
- : document.getElementById(elementId);
178
- if (!element) {
179
- console.error("invalid html element: " + elementId);
180
- return;
181
- }
182
-
183
- if (cornerstone.getEnabledElements().length == 0) {
184
- cornerstone.enable(element);
185
- }
186
-
187
- let renderPromise = new Promise(resolve => {
188
- // check if imageId is already stored in fileManager
189
- const imageId = getFileImageId(file);
190
- if (imageId) {
191
- cornerstone.loadImage(imageId).then(function (image) {
192
- cornerstone.displayImage(element, image);
193
- let viewport = cornerstone.getViewport(element);
194
- viewport.displayedArea.brhc.x = image.width;
195
- viewport.displayedArea.brhc.y = image.height;
196
- cornerstone.setViewport(element, viewport);
197
- cornerstone.fitToWindow(element);
198
- csToolsCreateStack(element);
199
- resolve(image);
200
- });
201
- }
202
- });
203
- return renderPromise;
204
- };
205
-
206
- /**
207
- * Render an image (png or jpg) from web url on a html div using cornerstone
208
- * @instance
209
- * @function renderWebImage
210
- * @param {String} url - The image data url
211
- * @param {String} elementId - The html div id used for rendering or its DOM HTMLElement
212
- * @returns {Promise} - Return a promise which will resolve when image is displayed
213
- */
214
- export const renderWebImage = function (url, elementId) {
215
- let element = isElement(elementId)
216
- ? elementId
217
- : document.getElementById(elementId);
218
- if (!element) {
219
- console.error("invalid html element: " + elementId);
220
- return;
221
- }
222
- let renderPromise = new Promise(resolve => {
223
- cornerstone.enable(element);
224
- cornerstone.loadImage(url).then(function (image) {
225
- cornerstone.displayImage(element, image);
226
- csToolsCreateStack(element);
227
- resolve(image);
228
- });
229
- });
230
- return renderPromise;
231
- };
232
-
233
- /**
234
- * Unrender an image on a html div using cornerstone
235
- * @instance
236
- * @function disableViewport
237
- * @param {String} elementId - The html div id used for rendering or its DOM HTMLElement
238
- */
239
- export const disableViewport = function (elementId) {
240
- let element = isElement(elementId)
241
- ? elementId
242
- : document.getElementById(elementId);
243
- if (!element) {
244
- console.error("invalid html element: " + elementId);
245
- return;
246
- }
247
- // toggleMouseHandlers(elementId, true); // flagged true to disable handlers
248
- toggleMouseToolsListeners(elementId, true);
249
- cornerstone.disable(element);
250
- };
251
-
252
- /**
253
- * Unrender an image on a html div using cornerstone
254
- * Remove image from cornerstone cache and remove from store
255
- * @instance
256
- * @function unloadViewport
257
- * @param {String} elementId - The html div id used for rendering or its DOM HTMLElement
258
- * @param {String} seriesId - The id of the serie
259
- */
260
- export const unloadViewport = function (elementId, seriesId) {
261
- disableViewport(elementId);
262
-
263
- if (!seriesId) {
264
- console.warn(
265
- "seriesId not provided, use disableViewport if you do not want to uncache images"
266
- );
267
- }
268
- // remove images from cornerstone cache
269
- if (seriesId && has(larvitar_store.get("series"), seriesId)) {
270
- clearImageCache(seriesId);
271
- }
272
- larvitar_store.deleteViewport(elementId);
273
- };
274
-
275
- /**
276
- * Resize a viewport using cornerstone resize
277
- * And forcing fit to window
278
- * @instance
279
- * @function resizeViewport
280
- * @param {String} elementId - The html div id used for rendering or its DOM HTMLElement
281
- */
282
- export const resizeViewport = function (elementId) {
283
- let element = isElement(elementId)
284
- ? elementId
285
- : document.getElementById(elementId);
286
- if (!element) {
287
- console.error("invalid html element: " + elementId);
288
- return;
289
- }
290
- cornerstone.resize(element, true); // true flag forces fitToWindow
291
- };
292
-
293
- /**
294
- * Cache image and render it in a html div using cornerstone
295
- * @instance
296
- * @function renderImage
297
- * @param {Object} seriesStack - The original series data object
298
- * @param {String} elementId - The html div id used for rendering or its DOM HTMLElement
299
- * @param {Object} defaultProps - Optional default props
300
- * @return {Promise} Return a promise which will resolve when image is displayed
301
- */
302
- export const renderImage = function (seriesStack, elementId, defaultProps) {
303
- let t0 = performance.now();
304
- // get element and enable it
305
- let element = isElement(elementId)
306
- ? elementId
307
- : document.getElementById(elementId);
308
- if (!element) {
309
- console.error("invalid html element: " + elementId);
310
- return;
311
- }
312
- cornerstone.enable(element);
313
-
314
- let series = { ...seriesStack };
315
-
316
- larvitar_store.set("renderingStatus", [elementId, false]);
317
- let data = getSeriesData(series, defaultProps);
318
- if (!data.imageId) {
319
- console.warn("Error during renderImage: imageId has not been loaded yet.");
320
- return;
321
- }
322
-
323
- let renderPromise = new Promise(resolve => {
324
- // load and display one image (imageId)
325
- cornerstone.loadImage(data.imageId).then(function (image) {
326
- cornerstone.displayImage(element, image);
327
-
328
- if (series.layer) {
329
- // assign the image to its layer and return its id
330
- series.layer.id = cornerstone.addLayer(
331
- element,
332
- image,
333
- series.layer.options
334
- );
335
- }
336
-
337
- let viewport = cornerstone.getViewport(element);
338
-
339
- // window width and window level
340
- // are stored in specific dicom tags
341
- // (x00281050 and x00281051)
342
- // if not present check in image object
343
- data.ww = data.ww ? data.ww : image.windowWidth;
344
- data.wc = data.wc ? data.wc : image.windowCenter;
345
- data.defaultWW = data.defaultWW ? data.defaultWW : data.ww;
346
- data.defaultWC = data.defaultWC ? data.defaultWC : data.wc;
347
-
348
- cornerstone.fitToWindow(element);
349
-
350
- if (defaultProps && has(defaultProps, "scale")) {
351
- viewport.scale = defaultProps["scale"];
352
- cornerstone.setViewport(element, viewport);
353
- }
354
-
355
- if (
356
- defaultProps &&
357
- has(defaultProps, "tr_x") &&
358
- has(defaultProps, "tr_y")
359
- ) {
360
- viewport.translation.x = defaultProps["tr_x"];
361
- viewport.translation.y = defaultProps["tr_y"];
362
- cornerstone.setViewport(element, viewport);
363
- }
364
-
365
- // color maps
366
- if (
367
- defaultProps &&
368
- has(defaultProps, "colormap") &&
369
- image.color == false
370
- ) {
371
- applyColorMap(defaultProps["colormap"]);
372
- }
373
-
374
- let storedViewport = cornerstone.getViewport(element);
375
- storeViewportData(image, elementId, storedViewport, data);
376
- larvitar_store.set("renderingStatus", [elementId, true]);
377
- let t1 = performance.now();
378
- console.log(`Call to renderImage took ${t1 - t0} milliseconds.`);
379
-
380
- let uri = cornerstoneDICOMImageLoader.wadouri.parseImageId(
381
- data.imageId
382
- ).url;
383
- cornerstoneDICOMImageLoader.wadouri.dataSetCacheManager.unload(uri);
384
- image = null;
385
- series = null;
386
- data = null;
387
- resolve();
388
- });
389
- });
390
-
391
- csToolsCreateStack(element, series.imageIds, data.imageIndex - 1);
392
- toggleMouseToolsListeners(elementId);
393
-
394
- return renderPromise;
395
- };
396
-
397
- /**
398
- * Update the cornerstone image with new imageIndex
399
- * @instance
400
- * @function updateImage
401
- * @param {Object} series - The original series data object
402
- * @param {String} elementId - The html div id used for rendering or its DOM HTMLElement
403
- * @param {Number} imageIndex - The index of the image to be rendered
404
- * @param {Boolean} cacheImage - A flag to handle image cache
405
- */
406
- export const updateImage = function (
407
- series,
408
- elementId,
409
- imageIndex,
410
- cacheImage
411
- ) {
412
- let element = isElement(elementId)
413
- ? elementId
414
- : document.getElementById(elementId);
415
- if (!element) {
416
- console.log("not element");
417
- return;
418
- }
419
- let imageId = series.imageIds[imageIndex];
420
-
421
- if (imageId) {
422
- if (series.is4D) {
423
- const timestamp = series.instances[imageId].metadata.contentTime;
424
- const timeId =
425
- series.instances[imageId].metadata.temporalPositionIdentifier - 1; // timeId from 0 to N
426
- larvitar_store.set("timeId", [elementId, timeId]);
427
- larvitar_store.set("timestamp", [elementId, timestamp]);
428
- }
429
-
430
- if (cacheImage) {
431
- cornerstone.loadAndCacheImage(imageId).then(function (image) {
432
- cornerstone.displayImage(element, image);
433
- larvitar_store.set("sliceId", [elementId, imageIndex]);
434
- larvitar_store.set("minPixelValue", [elementId, image.minPixelValue]);
435
- larvitar_store.set("maxPixelValue", [elementId, image.maxPixelValue]);
436
- });
437
- } else {
438
- cornerstone.loadImage(imageId).then(function (image) {
439
- cornerstone.displayImage(element, image);
440
- larvitar_store.set("sliceId", [elementId, imageIndex]);
441
- larvitar_store.set("minPixelValue", [elementId, image.minPixelValue]);
442
- larvitar_store.set("maxPixelValue", [elementId, image.maxPixelValue]);
443
- });
444
- }
445
- } else {
446
- console.warn(
447
- `Error: wrong image index ${imageIndex}, no imageId available`
448
- );
449
- }
450
- };
451
-
452
- /**
453
- * Reset viewport values (scale, translation and wwwc)
454
- * @instance
455
- * @function resetViewports
456
- * @param {Array} elementIds - The array of hmtl div ids
457
- */
458
- export const resetViewports = function (elementIds) {
459
- each(elementIds, function (elementId) {
460
- let element = document.getElementById(elementId);
461
- if (!element) {
462
- console.error("invalid html element: " + elementId);
463
- return;
464
- }
465
- let viewport = cornerstone.getViewport(element);
466
- viewport.scale = larvitar_store.get(
467
- "viewports",
468
- elementId,
469
- "default",
470
- "scale"
471
- );
472
-
473
- viewport.rotation = larvitar_store.get(
474
- "viewports",
475
- elementId,
476
- "default",
477
- "rotation"
478
- );
479
- viewport.translation.x = larvitar_store.get(
480
- "viewports",
481
- elementId,
482
- "default",
483
- "translation",
484
- "x"
485
- );
486
- viewport.translation.y = larvitar_store.get(
487
- "viewports",
488
- elementId,
489
- "default",
490
- "translation",
491
- "y"
492
- );
493
- viewport.voi.windowWidth = larvitar_store.get(
494
- "viewports",
495
- elementId,
496
- "default",
497
- "voi",
498
- "windowWidth"
499
- );
500
- viewport.voi.windowCenter = larvitar_store.get(
501
- "viewports",
502
- elementId,
503
- "default",
504
- "voi",
505
- "windowCenter"
506
- );
507
-
508
- viewport.hflip = false;
509
- viewport.vflip = false;
510
- viewport.invert = false;
511
-
512
- cornerstone.setViewport(element, viewport);
513
- cornerstone.fitToWindow(element);
514
- cornerstone.updateImage(element);
515
-
516
- larvitar_store.set("scale", [elementId, viewport.scale]);
517
- larvitar_store.set("rotation", [elementId, viewport.rotation]);
518
- larvitar_store.set("translation", [
519
- elementId,
520
- viewport.translation.x,
521
- viewport.translation.y
522
- ]);
523
- larvitar_store.set("contrast", [
524
- elementId,
525
- viewport.voi.windowWidth,
526
- viewport.voi.windowCenter
527
- ]);
528
- });
529
- };
530
-
531
- /**
532
- * Update viewport data in store
533
- * @instance
534
- * @function updateViewportData
535
- * @param {String} elementId - The html div id used for rendering or its DOM HTMLElement
536
- * @param {Object} viewportData - The new viewport data
537
- */
538
- export const updateViewportData = function (
539
- elementId,
540
- viewportData,
541
- activeTool
542
- ) {
543
- let element = isElement(elementId)
544
- ? elementId
545
- : document.getElementById(elementId);
546
- if (!element) {
547
- console.error("invalid html element: " + elementId);
548
- return;
549
- }
550
- switch (activeTool) {
551
- case "Wwwc":
552
- case "WwwcRegion":
553
- // sync viewports if needed
554
- let elements = cornerstone.getEnabledElements();
555
- each(elements, function (el) {
556
- larvitar_store.set("contrast", [
557
- el.element.id,
558
- viewportData.voi.windowWidth,
559
- viewportData.voi.windowCenter
560
- ]);
561
- });
562
- break;
563
- case "Pan":
564
- larvitar_store.set("translation", [
565
- elementId,
566
- viewportData.translation.x,
567
- viewportData.translation.y
568
- ]);
569
- break;
570
- case "Zoom":
571
- larvitar_store.set("scale", [elementId, viewportData.scale]);
572
- break;
573
- case "Rotate":
574
- larvitar_store.set("rotation", [elementId, viewportData.rotation]);
575
- break;
576
- case "mouseWheel":
577
- const isTimeserie = larvitar_store.get(
578
- "viewports",
579
- elementId,
580
- "isTimeserie"
581
- );
582
- if (isTimeserie) {
583
- const index = viewportData.newImageIdIndex;
584
- const timeId = larvitar_store.get("viewports", elementId, "timeIds")[
585
- index
586
- ];
587
- const timestamp = larvitar_store.get(
588
- "viewports",
589
- elementId,
590
- "timestamps"
591
- )[index];
592
- larvitar_store.set("timeId", [elementId, timeId]);
593
- larvitar_store.set("timestamp", [elementId, timestamp]);
594
- }
595
- break;
596
- default:
597
- break;
598
- }
599
- };
600
-
601
- /**
602
- * Store the viewport data into internal storage
603
- * @instance
604
- * @function storeViewportData
605
- * @param {Object} image - The cornerstone image frame
606
- * @param {String} elementId - The html div id used for rendering
607
- * @param {String} viewport - The viewport tag name
608
- * @param {Object} data - The viewport data object
609
- */
610
- export const storeViewportData = function (image, elementId, viewport, data) {
611
- larvitar_store.set("dimensions", [elementId, data.rows, data.cols]);
612
- larvitar_store.set("spacing", [elementId, data.spacing_x, data.spacing_y]);
613
- larvitar_store.set("thickness", [elementId, data.thickness]);
614
- larvitar_store.set("minPixelValue", [elementId, image.minPixelValue]);
615
- larvitar_store.set("maxPixelValue", [elementId, image.maxPixelValue]);
616
- // slice id from 0 to n - 1
617
- larvitar_store.set("minSliceId", [elementId, 0]);
618
- larvitar_store.set("sliceId", [elementId, data.imageIndex]);
619
- larvitar_store.set("maxSliceId", [elementId, data.numberOfSlices - 1]);
620
-
621
- if (data.isTimeserie) {
622
- larvitar_store.set("minTimeId", [elementId, 0]);
623
- larvitar_store.set("timeId", [elementId, data.timeIndex]);
624
- larvitar_store.set("maxTimeId", [
625
- elementId,
626
- data.numberOfTemporalPositions - 1
627
- ]);
628
- let maxSliceId = data.numberOfSlices * data.numberOfTemporalPositions - 1;
629
- larvitar_store.set("maxSliceId", [elementId, maxSliceId]);
630
-
631
- larvitar_store.set("timestamp", [elementId, data.timestamp]);
632
- larvitar_store.set("timestamps", [elementId, data.timestamps]);
633
- larvitar_store.set("timeIds", [elementId, data.timeIds]);
634
- } else {
635
- larvitar_store.set("minTimeId", [elementId, 0]);
636
- larvitar_store.set("timeId", [elementId, 0]);
637
- larvitar_store.set("maxTimeId", [elementId, 0]);
638
- larvitar_store.set("timestamps", [elementId, []]);
639
- larvitar_store.set("timeIds", [elementId, []]);
640
- }
641
-
642
- larvitar_store.set("defaultViewport", [
643
- elementId,
644
- viewport.scale,
645
- viewport.rotation,
646
- viewport.translation.x,
647
- viewport.translation.y,
648
- data.defaultWW,
649
- data.defaultWC
650
- ]);
651
- larvitar_store.set("scale", [elementId, viewport.scale]);
652
- larvitar_store.set("rotation", [elementId, viewport.rotation]);
653
- larvitar_store.set("translation", [
654
- elementId,
655
- viewport.translation.x,
656
- viewport.translation.y
657
- ]);
658
- larvitar_store.set("contrast", [
659
- elementId,
660
- viewport.voi.windowWidth,
661
- viewport.voi.windowCenter
662
- ]);
663
- larvitar_store.set("isColor", [elementId, data.isColor]);
664
- larvitar_store.set("isMultiframe", [elementId, data.isMultiframe]);
665
- larvitar_store.set("isTimeserie", [elementId, data.isTimeserie]);
666
- larvitar_store.set("isPDF", [elementId, false]);
667
- };
668
-
669
- /**
670
- * Invert pixels of an image
671
- * @instance
672
- * @function invertImage
673
- * @param {Object} elementId - The html div id used for rendering or its DOM HTMLElement
674
- */
675
- export const invertImage = function (elementId) {
676
- let element = isElement(elementId)
677
- ? elementId
678
- : document.getElementById(elementId);
679
- if (!element) {
680
- console.error("invalid html element: " + elementId);
681
- return;
682
- }
683
- let viewport = cornerstone.getViewport(element);
684
- viewport.invert = !viewport.invert;
685
- cornerstone.setViewport(element, viewport);
686
- };
687
-
688
- /**
689
- * Flip image around horizontal axis
690
- * @instance
691
- * @function flipImageHorizontal
692
- * @param {Object} elementId - The html div id used for rendering or its DOM HTMLElement
693
- */
694
- export const flipImageHorizontal = function (elementId) {
695
- let element = isElement(elementId)
696
- ? elementId
697
- : document.getElementById(elementId);
698
- if (!element) {
699
- console.error("invalid html element: " + elementId);
700
- return;
701
- }
702
- let viewport = cornerstone.getViewport(element);
703
- viewport.hflip = !viewport.hflip;
704
- cornerstone.setViewport(element, viewport);
705
- };
706
-
707
- /**
708
- * Flip image around vertical axis
709
- * @instance
710
- * @function flipImageVertical
711
- * @param {Object} elementId - The html div id used for rendering or its DOM HTMLElement
712
- */
713
- export const flipImageVertical = function (elementId) {
714
- let element = isElement(elementId)
715
- ? elementId
716
- : document.getElementById(elementId);
717
- if (!element) {
718
- console.error("invalid html element: " + elementId);
719
- return;
720
- }
721
- let viewport = cornerstone.getViewport(element);
722
- viewport.vflip = !viewport.vflip;
723
- cornerstone.setViewport(element, viewport);
724
- };
725
-
726
- /**
727
- * Rotate image by 90° in left direction
728
- * @instance
729
- * @function rotateImageLeft
730
- * @param {Object} elementId - The html div id used for rendering or its DOM HTMLElement
731
- */
732
- export const rotateImageLeft = function (elementId) {
733
- let element = isElement(elementId)
734
- ? elementId
735
- : document.getElementById(elementId);
736
- if (!element) {
737
- console.error("invalid html element: " + elementId);
738
- return;
739
- }
740
- let viewport = cornerstone.getViewport(element);
741
- viewport.rotation -= 90;
742
- cornerstone.setViewport(element, viewport);
743
- };
744
-
745
- /**
746
- * Rotate image by 90° in right direction
747
- * @instance
748
- * @function rotateImageRight
749
- * @param {Object} elementId - The html div id used for rendering or its DOM HTMLElement
750
- */
751
- export const rotateImageRight = function (elementId) {
752
- let element = isElement(elementId)
753
- ? elementId
754
- : document.getElementById(elementId);
755
- if (!element) {
756
- console.error("invalid html element: " + elementId);
757
- return;
758
- }
759
- let viewport = cornerstone.getViewport(element);
760
- viewport.rotation += 90;
761
- cornerstone.setViewport(element, viewport);
762
- };
763
-
764
- /* Internal module functions */
765
-
766
- /**
767
- * Get series metadata from default props and series' metadata
768
- * @instance
769
- * @function getSeriesData
770
- * @param {Object} series - The parsed data series
771
- * @param {Object} defaultProps - Optional default properties
772
- * @return {Object} data - A data dictionary with parsed tags' values
773
- */
774
- let getSeriesData = function (series, defaultProps) {
775
- let data = {};
776
- if (series.isMultiframe) {
777
- data.isMultiframe = true;
778
- data.numberOfSlices = series.imageIds.length;
779
- data.imageIndex = 0;
780
- data.imageId = series.imageIds[data.imageIndex];
781
- } else if (series.is4D) {
782
- data.isMultiframe = false;
783
- data.isTimeserie = true;
784
- // check with real indices
785
- data.numberOfSlices = series.numberOfImages;
786
- data.numberOfTemporalPositions = series.numberOfTemporalPositions;
787
- data.imageIndex = 0;
788
- data.timeIndex = 0;
789
- data.timestamp = series.instances[series.imageIds[0]].metadata["x00080033"];
790
- data.imageId = series.imageIds[data.imageIndex];
791
- data.timestamps = [];
792
- data.timeIds = [];
793
- each(series.imageIds, function (imageId) {
794
- data.timestamps.push(series.instances[imageId].metadata.contentTime);
795
- data.timeIds.push(
796
- series.instances[imageId].metadata.temporalPositionIdentifier - 1 // timeId from 0 to N
797
- );
798
- });
799
- } else {
800
- data.isMultiframe = false;
801
- data.numberOfSlices =
802
- defaultProps && has(defaultProps, "numberOfSlices")
803
- ? defaultProps["numberOfSlices"]
804
- : series.imageIds.length;
805
-
806
- data.imageIndex =
807
- defaultProps &&
808
- has(defaultProps, "sliceNumber") &&
809
- defaultProps["sliceNumber"] >= 0 && // slice number between 0 and n-1
810
- defaultProps["sliceNumber"] < data.numberOfSlices
811
- ? defaultProps["sliceNumber"]
812
- : Math.floor(data.numberOfSlices / 2);
813
-
814
- data.imageId = series.imageIds[data.imageIndex];
815
- }
816
- data.isColor = series.color;
817
- data.isPDF = series.isPDF;
818
-
819
- // rows, cols and x y z spacing
820
- data.rows = series.instances[series.imageIds[0]].metadata["x00280010"];
821
- data.cols = series.instances[series.imageIds[0]].metadata["x00280011"];
822
- data.thickness = series.instances[series.imageIds[0]].metadata["x00180050"];
823
- data.spacing_x = series.instances[series.imageIds[0]].metadata["x00280030"]
824
- ? series.instances[series.imageIds[0]].metadata["x00280030"][0]
825
- : null;
826
- data.spacing_y = series.instances[series.imageIds[0]].metadata["x00280030"]
827
- ? series.instances[series.imageIds[0]].metadata["x00280030"][1]
828
- : null;
829
-
830
- // window center and window width
831
- data.wc =
832
- defaultProps && has(defaultProps, "wc")
833
- ? defaultProps["wc"]
834
- : series.instances[series.imageIds[0]].metadata["x00281050"];
835
-
836
- data.ww =
837
- defaultProps && has(defaultProps, "ww")
838
- ? defaultProps["ww"]
839
- : series.instances[series.imageIds[0]].metadata["x00281051"];
840
-
841
- // default values for reset
842
- data.defaultWW =
843
- defaultProps && has(defaultProps, "defaultWW")
844
- ? defaultProps["defaultWW"]
845
- : data.ww;
846
- data.defaultWC =
847
- defaultProps && has(defaultProps, "defaultWC")
848
- ? defaultProps["defaultWC"]
849
- : data.wc;
850
-
851
- if (data.rows == null || data.cols == null) {
852
- console.error("invalid image metadata");
853
- larvitar_store.set("errorLog", "Invalid Image Metadata");
854
- return;
855
- } else {
856
- larvitar_store.set("errorLog", "");
857
- }
858
-
859
- return data;
860
- };