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,5 +1,5 @@
1
1
  /** @module loaders/multiframeLoader
2
- * @desc This file is a custom wado loader for multiframe images
2
+ * @desc This file is a custom DICOM loader for multiframe images
3
3
  */
4
4
 
5
5
  // external libraries
@@ -13,13 +13,20 @@ import {
13
13
  getLarvitarManager
14
14
  } from "./commonLoader";
15
15
  import { parseDataSet } from "../imageParsing";
16
+ import type {
17
+ Image,
18
+ ImageFrame,
19
+ LarvitarManager,
20
+ MetaData,
21
+ Series
22
+ } from "../types";
16
23
 
17
24
  // global module variables
18
25
  let customImageLoaderCounter = 0;
19
26
 
20
27
  // Local cache used to store multiframe datasets to avoid reading and parsing
21
28
  // the whole file to show a single frame.
22
- let multiframeDatasetCache = null;
29
+ let multiframeDatasetCache: { [key: string]: Series | null } | null = null;
23
30
  /*
24
31
  * This module provides the following functions to be exported:
25
32
  * loadMultiFrameImage(elementId)
@@ -35,25 +42,26 @@ let multiframeDatasetCache = null;
35
42
  * @param {String} imageId - ImageId tag
36
43
  * @returns {Function} Custom Image Creation Function
37
44
  */
38
- export const loadMultiFrameImage = function (imageId) {
45
+ export const loadMultiFrameImage = function (imageId: string) {
39
46
  let parsedImageId = cornerstoneDICOMImageLoader.wadouri.parseImageId(imageId);
40
47
  let rootImageId = parsedImageId.scheme + ":" + parsedImageId.url;
41
48
  let imageTracker = getLarvitarImageTracker();
42
49
  let seriesId = imageTracker[rootImageId];
43
- let manager = getLarvitarManager();
50
+ let manager = getLarvitarManager() as LarvitarManager;
44
51
  if (multiframeDatasetCache === null) {
45
52
  multiframeDatasetCache = {};
46
53
  }
54
+
47
55
  if (multiframeDatasetCache[rootImageId]) {
48
56
  multiframeDatasetCache[rootImageId] = multiframeDatasetCache[rootImageId];
49
57
  } else if (manager) {
50
- multiframeDatasetCache[rootImageId] = manager[seriesId];
58
+ multiframeDatasetCache[rootImageId] = manager[seriesId] as Series;
51
59
  } else {
52
60
  throw new Error("No multiframe dataset found for seriesId: " + seriesId);
53
61
  }
54
62
 
55
63
  let metadata =
56
- multiframeDatasetCache[rootImageId].instances[imageId].metadata;
64
+ multiframeDatasetCache[rootImageId]?.instances[imageId].metadata;
57
65
  return createCustomImage(rootImageId, imageId, parsedImageId.frame, metadata);
58
66
  };
59
67
 
@@ -64,65 +72,66 @@ export const loadMultiFrameImage = function (imageId) {
64
72
  * @param {String} seriesId - SeriesId tag
65
73
  * @param {Object} serie - parsed serie object
66
74
  */
67
- export const buildMultiFrameImage = function (seriesId, serie) {
75
+ export const buildMultiFrameImage = function (seriesId: string, serie: Series) {
68
76
  let t0 = performance.now();
69
77
  let manager = getLarvitarManager();
70
78
  let imageTracker = getLarvitarImageTracker();
71
- let numberOfFrames =
72
- serie.instances[serie.imageIds[0]].metadata.numberOfFrames;
73
- let frameTime = serie.instances[serie.imageIds[0]].metadata.frameTime;
74
- let frameDelay = serie.instances[serie.imageIds[0]].metadata.frameDelay
75
- ? serie.instances[serie.imageIds[0]].metadata.frameDelay
76
- : 0;
77
-
78
- each(serie.imageIds, function (instanceId) {
79
- let dataSet = serie.instances[instanceId].dataSet;
80
- let metadata = serie.instances[instanceId].metadata;
81
- let imageId = getMultiFrameImageId("multiFrameLoader");
82
- imageTracker[imageId] = seriesId;
83
-
84
- // check if manager exists for this seriesId
85
- if (!manager[seriesId]) {
86
- manager[seriesId] = serie;
87
- manager[seriesId].imageIds = [];
88
- manager[seriesId].instances = {};
89
- }
90
-
91
- each(range(numberOfFrames), function (frameNumber) {
92
- let frameImageId = imageId + "?frame=" + frameNumber;
93
- // EXTRACT MULTIFRAME METADATA (x52009230) Per-frame Functional Groups Sequence
94
- let frameMetadata = { ...metadata };
79
+ let numberOfFrames = serie.metadata!.numberOfFrames!;
80
+ let frameTime = serie.metadata!.frameTime;
81
+ let frameDelay = serie.metadata!.frameDelay ? serie.metadata!.frameDelay : 0;
82
+ let rWaveTimeVector = serie.metadata!.rWaveTimeVector;
83
+ let sopInstanceUID = serie.metadata!["x00080018"] as string;
84
+ let dataSet = serie.dataSet;
85
+ let imageId = getMultiFrameImageId("multiFrameLoader");
86
+ imageTracker[imageId] = seriesId;
87
+
88
+ // check if manager exists for this seriesId
89
+ if (!manager[seriesId]) {
90
+ manager[seriesId] = serie;
91
+ manager[seriesId].imageIds = [];
92
+ manager[seriesId].instances = {};
93
+ }
95
94
 
96
- parseDataSet(dataSet, frameMetadata, {
97
- tags: ["x52009230"],
98
- frameId: frameNumber
99
- });
95
+ each(range(numberOfFrames as number), function (frameNumber) {
96
+ let frameImageId = imageId + "?frame=" + frameNumber;
97
+ // EXTRACT MULTIFRAME METADATA (x52009230) Per-frame Functional Groups Sequence
98
+ let frameMetadata = { ...serie.metadata! };
100
99
 
101
- // store file references
102
- manager[seriesId].seriesUID = seriesId;
103
- manager[seriesId].studyUID = metadata["x0020000d"];
104
- manager[seriesId].modality = metadata["x00080060"];
105
- manager[seriesId].color = cornerstoneDICOMImageLoader.isColorImage(
106
- metadata["x00280004"]
107
- );
108
- manager[seriesId].isMultiframe = true;
109
- manager[seriesId].currentImageIdIndex = 0;
110
- manager[seriesId].numberOfFrames = numberOfFrames;
111
- manager[seriesId].frameTime = frameTime;
112
- manager[seriesId].frameDelay = frameDelay;
113
- manager[seriesId].numberOfImages = undefined;
114
- manager[seriesId].bytes = serie.bytes;
115
- manager[seriesId].imageIds.push(frameImageId);
116
- manager[seriesId].instances[frameImageId] = {
117
- instanceId: instanceId,
118
- frame: frameNumber,
119
- metadata: frameMetadata
120
- };
121
- manager[seriesId].dataSet = dataSet;
122
- manager[seriesId].seriesDescription =
123
- serie.instances[serie.imageIds[0]].metadata.seriesDescription;
100
+ parseDataSet(dataSet!, frameMetadata, {
101
+ tags: ["x52009230"],
102
+ frameId: frameNumber
124
103
  });
104
+
105
+ // TODO-ts REMOVE "AS" WHEN METADATA VALUES ARE TYPED
106
+ // store file references
107
+ const managerSeriesId = manager[seriesId] as Series;
108
+ managerSeriesId.seriesUID = seriesId;
109
+ managerSeriesId.studyUID = serie.metadata!["x0020000d"] as string;
110
+ managerSeriesId.modality = serie.metadata!["x00080060"] as string;
111
+ managerSeriesId.color = cornerstoneDICOMImageLoader.isColorImage(
112
+ serie.metadata!["x00280004"]
113
+ );
114
+
115
+ managerSeriesId.isMultiframe = true;
116
+ managerSeriesId.currentImageIdIndex = 0;
117
+ managerSeriesId.numberOfFrames = numberOfFrames;
118
+ managerSeriesId.frameTime = frameTime;
119
+ managerSeriesId.frameDelay = frameDelay;
120
+ managerSeriesId.rWaveTimeVector = rWaveTimeVector;
121
+ managerSeriesId.numberOfImages = undefined;
122
+ managerSeriesId.bytes = serie.bytes;
123
+ managerSeriesId.imageIds.push(frameImageId);
124
+ managerSeriesId.instanceUIDs[sopInstanceUID] = imageId;
125
+ managerSeriesId.instances[frameImageId] = {
126
+ instanceId: sopInstanceUID,
127
+ frame: frameNumber,
128
+ metadata: frameMetadata
129
+ };
130
+ managerSeriesId.dataSet = dataSet || null;
131
+ managerSeriesId.seriesDescription = serie.metadata!
132
+ .seriesDescription as string;
125
133
  });
134
+
126
135
  let t1 = performance.now();
127
136
  console.log(`Call to buildMultiFrameImage took ${t1 - t0} milliseconds.`);
128
137
  };
@@ -134,7 +143,7 @@ export const buildMultiFrameImage = function (seriesId, serie) {
134
143
  * @param {String} customLoaderName The custom loader name
135
144
  * @return {String} the custom image id
136
145
  */
137
- export const getMultiFrameImageId = function (customLoaderName) {
146
+ export const getMultiFrameImageId = function (customLoaderName: string) {
138
147
  let imageId = customLoaderName + "://" + customImageLoaderCounter;
139
148
  customImageLoaderCounter++;
140
149
  return imageId;
@@ -146,20 +155,26 @@ export const getMultiFrameImageId = function (customLoaderName) {
146
155
  * @function clearMultiFrameCache
147
156
  * @param {String} seriesId - SeriesId tag
148
157
  */
149
- export const clearMultiFrameCache = function (seriesId) {
158
+ export const clearMultiFrameCache = function (seriesId: string) {
150
159
  each(multiframeDatasetCache, function (image, imageId) {
160
+ if (!image) {
161
+ return;
162
+ }
151
163
  if (seriesId == image.seriesUID || !seriesId) {
152
164
  if (image.dataSet) {
165
+ // @ts-ignore: modify external type ?
153
166
  image.dataSet.byteArray = null;
154
167
  }
155
168
  image.dataSet = null;
156
169
  image.elements = null;
157
170
  each(image.instances, function (instance) {
171
+ // @ts-ignore: is needed to clear the cache ?
158
172
  instance.metadata = null;
159
173
  });
174
+ // @ts-ignore: is needed to clear the cache ?
160
175
  image.instances = null;
161
- multiframeDatasetCache[imageId] = null;
162
- delete multiframeDatasetCache[imageId];
176
+ multiframeDatasetCache![imageId] = null;
177
+ delete multiframeDatasetCache![imageId];
163
178
  }
164
179
  });
165
180
  if (!seriesId) {
@@ -179,8 +194,13 @@ export const clearMultiFrameCache = function (seriesId) {
179
194
  * @param {Object} dataSet dataset object
180
195
  * @returns {Object} custom image object
181
196
  */
182
- let createCustomImage = function (id, imageId, frameIndex, metadata) {
183
- let options = {};
197
+ let createCustomImage = function (
198
+ id: string,
199
+ imageId: string,
200
+ frameIndex: number,
201
+ metadata?: MetaData
202
+ ) {
203
+ let options: { [key: string]: any } = {}; //TODO-ts change any to proper type when available
184
204
  // always preScale the pixel array unless it is asked not to
185
205
  options.preScale = {
186
206
  enabled:
@@ -189,10 +209,20 @@ let createCustomImage = function (id, imageId, frameIndex, metadata) {
189
209
  : false
190
210
  };
191
211
 
192
- let dataSet = multiframeDatasetCache[id].dataSet;
212
+ if (multiframeDatasetCache === null || !multiframeDatasetCache[id]) {
213
+ throw new Error("No multiframe dataset found for id: " + id);
214
+ }
215
+
216
+ let dataSet = (multiframeDatasetCache as { [key: string]: Series })[id]
217
+ .dataSet;
218
+
219
+ if (!dataSet) {
220
+ throw new Error("No dataset found for id: " + id);
221
+ }
222
+
193
223
  let pixelDataElement = dataSet.elements.x7fe00010;
194
224
  // Extract pixelData of the required frame
195
- let pixelData;
225
+ let pixelData: number[];
196
226
  try {
197
227
  if (pixelDataElement.encapsulatedPixelData) {
198
228
  pixelData = cornerstoneDICOMImageLoader.wadouri.getEncapsulatedImageFrame(
@@ -206,14 +236,17 @@ let createCustomImage = function (id, imageId, frameIndex, metadata) {
206
236
  );
207
237
  }
208
238
  } catch (error) {
209
- console.error(error);
239
+ throw new Error("No pixel data for id: " + id);
240
+ }
241
+
242
+ if (!metadata) {
243
+ throw new Error("No metadata for id: " + id);
210
244
  }
211
245
 
212
246
  let imageFrame = getImageFrame(metadata, dataSet);
213
247
  let transferSyntax = dataSet.string("x00020010");
214
248
 
215
249
  let canvas = window.document.createElement("canvas");
216
-
217
250
  // Get the scaling parameters from the metadata
218
251
  if (options.preScale.enabled) {
219
252
  const scalingParameters = cornerstoneDICOMImageLoader.getScalingParameters(
@@ -237,8 +270,8 @@ let createCustomImage = function (id, imageId, frameIndex, metadata) {
237
270
  options
238
271
  );
239
272
 
240
- let promise = new Promise((resolve, reject) => {
241
- decodePromise.then(function handleDecodeResponse(imageFrame) {
273
+ let promise: Promise<Image> = new Promise((resolve, reject) => {
274
+ decodePromise.then(function handleDecodeResponse(imageFrame: ImageFrame) {
242
275
  // This function uses the pixelData received as argument without manipulating
243
276
  // them: if the image is compressed, the decompress function should be called
244
277
  // before creating the custom image object (like the multiframe case).
@@ -260,35 +293,43 @@ let createCustomImage = function (id, imageId, frameIndex, metadata) {
260
293
  );
261
294
  }
262
295
 
263
- let image = {
296
+ let image: Partial<Image> = {
264
297
  imageId: imageId,
265
298
  color: cornerstoneDICOMImageLoader.isColorImage(
266
299
  imageFrame.photometricInterpretation
267
300
  ),
268
- columnPixelSpacing: pixelSpacing[1] ? pixelSpacing[1] : pixelSpacing, // check for specific spacing value
301
+ columnPixelSpacing: (pixelSpacing as number[])[1]
302
+ ? (pixelSpacing as number[])[1]
303
+ : (pixelSpacing as number), // check for specific spacing value
269
304
  columns: imageFrame.columns,
270
- data: dataSet,
305
+ data: dataSet ? dataSet : undefined,
271
306
  height: imageFrame.rows,
272
307
  floatPixelData: undefined,
273
- intercept: rescaleIntercept ? rescaleIntercept : 0,
308
+ intercept: (rescaleIntercept as number)
309
+ ? (rescaleIntercept as number)
310
+ : 0,
274
311
  invert: imageFrame.photometricInterpretation === "MONOCHROME1",
275
312
  minPixelValue: imageFrame.smallestPixelValue,
276
313
  maxPixelValue: imageFrame.largestPixelValue,
277
314
  render: undefined, // set below
278
- rowPixelSpacing: pixelSpacing[0] ? pixelSpacing[0] : pixelSpacing, // check for specific spacing value
315
+ rowPixelSpacing: (pixelSpacing as number[])[0]
316
+ ? (pixelSpacing as number[])[0]
317
+ : (pixelSpacing as number), // check for specific spacing value
279
318
  rows: imageFrame.rows,
280
319
  sizeInBytes: getSizeInBytes(),
281
- slope: rescaleSlope ? rescaleSlope : 1,
320
+ slope: (rescaleSlope as number) ? (rescaleSlope as number) : 1,
282
321
  width: imageFrame.columns,
283
- windowCenter: windowCenter,
284
- windowWidth: windowWidth,
322
+ windowCenter: windowCenter as number,
323
+ windowWidth: windowWidth as number,
285
324
  decodeTimeInMS: undefined, // TODO
286
- loadTimeInMS: undefined, // TODO
287
- render: undefined
325
+ loadTimeInMS: undefined // TODO
288
326
  };
289
327
  // add function to return pixel data
290
328
  image.getPixelData = function () {
291
- return imageFrame.pixelData;
329
+ if (imageFrame.pixelData === undefined) {
330
+ throw new Error("No pixel data for image " + imageId);
331
+ }
332
+ return Array.from(imageFrame.pixelData);
292
333
  };
293
334
 
294
335
  // convert color space if not isJPEGBaseline8BitColor
@@ -305,6 +346,10 @@ let createCustomImage = function (id, imageId, frameIndex, metadata) {
305
346
 
306
347
  let context = canvas.getContext("2d");
307
348
 
349
+ if (!context) {
350
+ throw new Error("Unable to get canvas context");
351
+ }
352
+
308
353
  let imageData = context.createImageData(
309
354
  imageFrame.columns,
310
355
  imageFrame.rows
@@ -319,10 +364,13 @@ let createCustomImage = function (id, imageId, frameIndex, metadata) {
319
364
  // Setup the renderer
320
365
  if (image.color) {
321
366
  image.getCanvas = function () {
322
- canvas.height = image.rows;
323
- canvas.width = image.columns;
367
+ canvas.height = image.rows || 0;
368
+ canvas.width = image.columns || 0;
324
369
  let context = canvas.getContext("2d");
325
- context.putImageData(imageFrame.imageData, 0, 0);
370
+ if (!context) {
371
+ throw new Error("Unable to get canvas context");
372
+ }
373
+ context.putImageData(imageFrame.imageData!, 0, 0);
326
374
  return canvas;
327
375
  };
328
376
  }
@@ -342,7 +390,12 @@ let createCustomImage = function (id, imageId, frameIndex, metadata) {
342
390
  if (image.color) {
343
391
  image.windowWidth = 255;
344
392
  image.windowCenter = 128;
345
- } else {
393
+ } else if (
394
+ image.maxPixelValue &&
395
+ image.minPixelValue &&
396
+ image.slope &&
397
+ image.intercept
398
+ ) {
346
399
  let maxVoi = image.maxPixelValue * image.slope + image.intercept;
347
400
  let minVoi = image.minPixelValue * image.slope + image.intercept;
348
401
  image.windowWidth = maxVoi - minVoi;
@@ -350,7 +403,7 @@ let createCustomImage = function (id, imageId, frameIndex, metadata) {
350
403
  }
351
404
  }
352
405
 
353
- resolve(image);
406
+ resolve(image as Image);
354
407
  }, reject);
355
408
  });
356
409
 
@@ -367,14 +420,16 @@ let createCustomImage = function (id, imageId, frameIndex, metadata) {
367
420
  * @function setPixelDataType
368
421
  * @param {Object} imageFrame The Id of the image
369
422
  */
370
- const setPixelDataType = function (imageFrame) {
423
+ const setPixelDataType = function (imageFrame: ImageFrame) {
371
424
  if (imageFrame.bitsAllocated === 16) {
372
425
  if (imageFrame.pixelRepresentation === 0) {
373
- imageFrame.pixelData = new Uint16Array(imageFrame.pixelData);
426
+ imageFrame.pixelData = new Uint16Array(
427
+ imageFrame.pixelData as Uint16Array
428
+ );
374
429
  } else {
375
- imageFrame.pixelData = new Int16Array(imageFrame.pixelData);
430
+ imageFrame.pixelData = new Int16Array(imageFrame.pixelData as Int16Array);
376
431
  }
377
432
  } else {
378
- imageFrame.pixelData = new Uint8Array(imageFrame.pixelData);
433
+ imageFrame.pixelData = new Uint8Array(imageFrame.pixelData as Uint8Array);
379
434
  }
380
435
  };