larvitar 2.0.5 → 2.0.7
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.
- package/README.md +2 -2
- package/dist/imaging/imageRendering.d.ts +1 -71
- package/dist/imaging/imageStore.d.ts +5 -0
- package/dist/imaging/loaders/commonLoader.d.ts +4 -4
- package/dist/imaging/loaders/nrrdLoader.d.ts +1 -51
- package/dist/larvitar.js +13 -1
- package/dist/larvitar.js.map +1 -1
- package/imaging/tools/types.d.ts +19 -19
- package/imaging/types.d.ts +110 -2
- package/package.json +7 -2
- package/.github/workflows/build-docs.yml +0 -59
- package/.github/workflows/codeql-analysis.yml +0 -71
- package/.github/workflows/deploy.yml +0 -37
- package/.vscode/settings.json +0 -4
- package/CODE_OF_CONDUCT.md +0 -76
- package/MIGRATION.md +0 -25
- package/bundler/webpack.common.js +0 -27
- package/bundler/webpack.dev.js +0 -23
- package/bundler/webpack.prod.js +0 -19
- package/decs.d.ts +0 -12
- package/dist/imaging/MetaDataReadable.d.ts +0 -41
- package/dist/imaging/MetaDataTypes.d.ts +0 -3489
- package/imaging/dataDictionary.json +0 -21866
- package/imaging/imageAnonymization.ts +0 -135
- package/imaging/imageColormaps.ts +0 -217
- package/imaging/imageContours.ts +0 -196
- package/imaging/imageIo.ts +0 -251
- package/imaging/imageLayers.ts +0 -121
- package/imaging/imageLoading.ts +0 -299
- package/imaging/imageParsing.ts +0 -444
- package/imaging/imagePresets.ts +0 -156
- package/imaging/imageRendering.ts +0 -1091
- package/imaging/imageReslice.ts +0 -87
- package/imaging/imageStore.ts +0 -487
- package/imaging/imageTags.ts +0 -609
- package/imaging/imageTools.js +0 -708
- package/imaging/imageUtils.ts +0 -1079
- package/imaging/loaders/commonLoader.ts +0 -275
- package/imaging/loaders/dicomLoader.ts +0 -66
- package/imaging/loaders/fileLoader.ts +0 -71
- package/imaging/loaders/multiframeLoader.ts +0 -435
- package/imaging/loaders/nrrdLoader.ts +0 -630
- package/imaging/loaders/resliceLoader.ts +0 -205
- package/imaging/monitors/memory.ts +0 -151
- package/imaging/monitors/performance.ts +0 -34
- package/imaging/parsers/ecg.ts +0 -54
- package/imaging/parsers/nrrd.js +0 -485
- package/imaging/tools/custom/4dSliceScrollTool.js +0 -146
- package/imaging/tools/custom/BorderMagnifyTool.js +0 -99
- package/imaging/tools/custom/contourTool.js +0 -1884
- package/imaging/tools/custom/diameterTool.js +0 -141
- package/imaging/tools/custom/editMaskTool.js +0 -141
- package/imaging/tools/custom/ellipticalRoiOverlayTool.js +0 -534
- package/imaging/tools/custom/polygonSegmentationMixin.js +0 -245
- package/imaging/tools/custom/polylineScissorsTool.js +0 -59
- package/imaging/tools/custom/rectangleRoiOverlayTool.js +0 -564
- package/imaging/tools/custom/seedTool.js +0 -342
- package/imaging/tools/custom/setLabelMap3D.ts +0 -242
- package/imaging/tools/custom/thresholdsBrushTool.js +0 -161
- package/imaging/tools/default.ts +0 -594
- package/imaging/tools/interaction.ts +0 -266
- package/imaging/tools/io.ts +0 -229
- package/imaging/tools/main.ts +0 -427
- package/imaging/tools/segmentation.ts +0 -532
- package/imaging/tools/segmentations.md +0 -38
- package/imaging/tools/state.ts +0 -74
- package/imaging/tools/strategies/eraseFreehand.js +0 -76
- package/imaging/tools/strategies/fillFreehand.js +0 -79
- package/imaging/tools/strategies/index.js +0 -2
- package/imaging/waveforms/ecg.ts +0 -191
- package/index.ts +0 -431
- package/jsdoc.json +0 -52
- package/rollup.config.js +0 -51
- package/template/.gitkeep +0 -0
- package/tsconfig.json +0 -102
- /package/imaging/{MetaDataReadable.ts → MetaDataReadable.d.ts} +0 -0
- /package/imaging/{MetaDataTypes.ts → MetaDataTypes.d.ts} +0 -0
|
@@ -1,435 +0,0 @@
|
|
|
1
|
-
/** @module loaders/multiframeLoader
|
|
2
|
-
* @desc This file is a custom DICOM loader for multiframe images
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
// external libraries
|
|
6
|
-
import { default as cornerstoneDICOMImageLoader } from "cornerstone-wado-image-loader";
|
|
7
|
-
import { each, range } from "lodash";
|
|
8
|
-
|
|
9
|
-
// internal libraries
|
|
10
|
-
import {
|
|
11
|
-
getImageFrame,
|
|
12
|
-
getLarvitarImageTracker,
|
|
13
|
-
getLarvitarManager
|
|
14
|
-
} from "./commonLoader";
|
|
15
|
-
import { parseDataSet } from "../imageParsing";
|
|
16
|
-
import type {
|
|
17
|
-
Image,
|
|
18
|
-
ImageFrame,
|
|
19
|
-
LarvitarManager,
|
|
20
|
-
MetaData,
|
|
21
|
-
Series
|
|
22
|
-
} from "../types";
|
|
23
|
-
|
|
24
|
-
// global module variables
|
|
25
|
-
let customImageLoaderCounter = 0;
|
|
26
|
-
|
|
27
|
-
// Local cache used to store multiframe datasets to avoid reading and parsing
|
|
28
|
-
// the whole file to show a single frame.
|
|
29
|
-
let multiframeDatasetCache: { [key: string]: Series | null } | null = null;
|
|
30
|
-
/*
|
|
31
|
-
* This module provides the following functions to be exported:
|
|
32
|
-
* loadMultiFrameImage(elementId)
|
|
33
|
-
* buildMultiFrameImage(seriesId, serie)
|
|
34
|
-
* getMultiFrameImageId(customLoaderName)
|
|
35
|
-
* clearMultiFrameCache()
|
|
36
|
-
*/
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Custom MultiFrame Loader Function
|
|
40
|
-
* @export
|
|
41
|
-
* @function loadMultiFrameImage
|
|
42
|
-
* @param {String} imageId - ImageId tag
|
|
43
|
-
* @returns {Function} Custom Image Creation Function
|
|
44
|
-
*/
|
|
45
|
-
export const loadMultiFrameImage = function (imageId: string) {
|
|
46
|
-
let parsedImageId = cornerstoneDICOMImageLoader.wadouri.parseImageId(imageId);
|
|
47
|
-
let rootImageId = parsedImageId.scheme + ":" + parsedImageId.url;
|
|
48
|
-
let imageTracker = getLarvitarImageTracker();
|
|
49
|
-
let seriesId = imageTracker[rootImageId];
|
|
50
|
-
let manager = getLarvitarManager() as LarvitarManager;
|
|
51
|
-
if (multiframeDatasetCache === null) {
|
|
52
|
-
multiframeDatasetCache = {};
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
if (multiframeDatasetCache[rootImageId]) {
|
|
56
|
-
multiframeDatasetCache[rootImageId] = multiframeDatasetCache[rootImageId];
|
|
57
|
-
} else if (manager) {
|
|
58
|
-
multiframeDatasetCache[rootImageId] = manager[seriesId] as Series;
|
|
59
|
-
} else {
|
|
60
|
-
throw new Error("No multiframe dataset found for seriesId: " + seriesId);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
let metadata =
|
|
64
|
-
multiframeDatasetCache[rootImageId]?.instances[imageId].metadata;
|
|
65
|
-
return createCustomImage(rootImageId, imageId, parsedImageId.frame, metadata);
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Build the multiframe layout in the larvitar Manager
|
|
70
|
-
* @export
|
|
71
|
-
* @function buildMultiFrameImage
|
|
72
|
-
* @param {String} seriesId - SeriesId tag
|
|
73
|
-
* @param {Object} serie - parsed serie object
|
|
74
|
-
*/
|
|
75
|
-
export const buildMultiFrameImage = function (seriesId: string, serie: Series) {
|
|
76
|
-
let t0 = performance.now();
|
|
77
|
-
let manager = getLarvitarManager();
|
|
78
|
-
let imageTracker = getLarvitarImageTracker();
|
|
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
|
-
}
|
|
94
|
-
|
|
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! };
|
|
99
|
-
|
|
100
|
-
parseDataSet(dataSet!, frameMetadata, {
|
|
101
|
-
tags: ["x52009230"],
|
|
102
|
-
frameId: frameNumber
|
|
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;
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
let t1 = performance.now();
|
|
136
|
-
console.log(`Call to buildMultiFrameImage took ${t1 - t0} milliseconds.`);
|
|
137
|
-
};
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* Get the custom imageId from custom loader
|
|
141
|
-
* @instance
|
|
142
|
-
* @function getMultiFrameImageId
|
|
143
|
-
* @param {String} customLoaderName The custom loader name
|
|
144
|
-
* @return {String} the custom image id
|
|
145
|
-
*/
|
|
146
|
-
export const getMultiFrameImageId = function (customLoaderName: string) {
|
|
147
|
-
let imageId = customLoaderName + "://" + customImageLoaderCounter;
|
|
148
|
-
customImageLoaderCounter++;
|
|
149
|
-
return imageId;
|
|
150
|
-
};
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* Clear the multiframe cache
|
|
154
|
-
* @instance
|
|
155
|
-
* @function clearMultiFrameCache
|
|
156
|
-
* @param {String} seriesId - SeriesId tag
|
|
157
|
-
*/
|
|
158
|
-
export const clearMultiFrameCache = function (seriesId: string) {
|
|
159
|
-
each(multiframeDatasetCache, function (image, imageId) {
|
|
160
|
-
if (!image) {
|
|
161
|
-
return;
|
|
162
|
-
}
|
|
163
|
-
if (seriesId == image.seriesUID || !seriesId) {
|
|
164
|
-
if (image.dataSet) {
|
|
165
|
-
// @ts-ignore: modify external type ?
|
|
166
|
-
image.dataSet.byteArray = null;
|
|
167
|
-
}
|
|
168
|
-
image.dataSet = null;
|
|
169
|
-
image.elements = null;
|
|
170
|
-
each(image.instances, function (instance) {
|
|
171
|
-
// @ts-ignore: is needed to clear the cache ?
|
|
172
|
-
instance.metadata = null;
|
|
173
|
-
});
|
|
174
|
-
// @ts-ignore: is needed to clear the cache ?
|
|
175
|
-
image.instances = null;
|
|
176
|
-
multiframeDatasetCache![imageId] = null;
|
|
177
|
-
delete multiframeDatasetCache![imageId];
|
|
178
|
-
}
|
|
179
|
-
});
|
|
180
|
-
if (!seriesId) {
|
|
181
|
-
multiframeDatasetCache = null;
|
|
182
|
-
}
|
|
183
|
-
};
|
|
184
|
-
|
|
185
|
-
/* Internal module functions */
|
|
186
|
-
|
|
187
|
-
/**
|
|
188
|
-
* Create the custom image object for cornerstone from custom image
|
|
189
|
-
* @instance
|
|
190
|
-
* @function createCustomImage
|
|
191
|
-
* @param {String} imageId The Id of the image
|
|
192
|
-
* @param {Object} metadata the metadata object
|
|
193
|
-
* @param {Object} pixelData pixel data object
|
|
194
|
-
* @param {Object} dataSet dataset object
|
|
195
|
-
* @returns {Object} custom image object
|
|
196
|
-
*/
|
|
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
|
|
204
|
-
// always preScale the pixel array unless it is asked not to
|
|
205
|
-
options.preScale = {
|
|
206
|
-
enabled:
|
|
207
|
-
options.preScale && options.preScale.enabled !== undefined
|
|
208
|
-
? options.preScale.enabled
|
|
209
|
-
: false
|
|
210
|
-
};
|
|
211
|
-
|
|
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
|
-
|
|
223
|
-
let pixelDataElement = dataSet.elements.x7fe00010;
|
|
224
|
-
// Extract pixelData of the required frame
|
|
225
|
-
let pixelData: number[];
|
|
226
|
-
try {
|
|
227
|
-
if (pixelDataElement.encapsulatedPixelData) {
|
|
228
|
-
pixelData = cornerstoneDICOMImageLoader.wadouri.getEncapsulatedImageFrame(
|
|
229
|
-
dataSet,
|
|
230
|
-
frameIndex
|
|
231
|
-
);
|
|
232
|
-
} else {
|
|
233
|
-
pixelData = cornerstoneDICOMImageLoader.wadouri.getUncompressedImageFrame(
|
|
234
|
-
dataSet,
|
|
235
|
-
frameIndex
|
|
236
|
-
);
|
|
237
|
-
}
|
|
238
|
-
} catch (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);
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
let imageFrame = getImageFrame(metadata, dataSet);
|
|
247
|
-
let transferSyntax = dataSet.string("x00020010");
|
|
248
|
-
|
|
249
|
-
let canvas = window.document.createElement("canvas");
|
|
250
|
-
// Get the scaling parameters from the metadata
|
|
251
|
-
if (options.preScale.enabled) {
|
|
252
|
-
const scalingParameters = cornerstoneDICOMImageLoader.getScalingParameters(
|
|
253
|
-
cornerstone.metaData,
|
|
254
|
-
imageId
|
|
255
|
-
);
|
|
256
|
-
|
|
257
|
-
if (scalingParameters) {
|
|
258
|
-
options.preScale = {
|
|
259
|
-
...options.preScale,
|
|
260
|
-
scalingParameters
|
|
261
|
-
};
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
const decodePromise = cornerstoneDICOMImageLoader.decodeImageFrame(
|
|
266
|
-
imageFrame,
|
|
267
|
-
transferSyntax,
|
|
268
|
-
pixelData,
|
|
269
|
-
canvas,
|
|
270
|
-
options
|
|
271
|
-
);
|
|
272
|
-
|
|
273
|
-
let promise: Promise<Image> = new Promise((resolve, reject) => {
|
|
274
|
-
decodePromise.then(function handleDecodeResponse(imageFrame: ImageFrame) {
|
|
275
|
-
// This function uses the pixelData received as argument without manipulating
|
|
276
|
-
// them: if the image is compressed, the decompress function should be called
|
|
277
|
-
// before creating the custom image object (like the multiframe case).
|
|
278
|
-
setPixelDataType(imageFrame);
|
|
279
|
-
|
|
280
|
-
let pixelSpacing = metadata.x00280030 ? metadata.x00280030 : 1.0;
|
|
281
|
-
let rescaleIntercept = metadata.x00281052;
|
|
282
|
-
let rescaleSlope = metadata.x00281053;
|
|
283
|
-
let windowCenter = metadata.x00281050;
|
|
284
|
-
let windowWidth = metadata.x00281051;
|
|
285
|
-
|
|
286
|
-
function getSizeInBytes() {
|
|
287
|
-
let bytesPerPixel = Math.round(imageFrame.bitsAllocated / 8);
|
|
288
|
-
return (
|
|
289
|
-
imageFrame.rows *
|
|
290
|
-
imageFrame.columns *
|
|
291
|
-
bytesPerPixel *
|
|
292
|
-
imageFrame.samplesPerPixel
|
|
293
|
-
);
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
let image: Partial<Image> = {
|
|
297
|
-
imageId: imageId,
|
|
298
|
-
color: cornerstoneDICOMImageLoader.isColorImage(
|
|
299
|
-
imageFrame.photometricInterpretation
|
|
300
|
-
),
|
|
301
|
-
columnPixelSpacing: (pixelSpacing as number[])[1]
|
|
302
|
-
? (pixelSpacing as number[])[1]
|
|
303
|
-
: (pixelSpacing as number), // check for specific spacing value
|
|
304
|
-
columns: imageFrame.columns,
|
|
305
|
-
data: dataSet ? dataSet : undefined,
|
|
306
|
-
height: imageFrame.rows,
|
|
307
|
-
floatPixelData: undefined,
|
|
308
|
-
intercept: (rescaleIntercept as number)
|
|
309
|
-
? (rescaleIntercept as number)
|
|
310
|
-
: 0,
|
|
311
|
-
invert: imageFrame.photometricInterpretation === "MONOCHROME1",
|
|
312
|
-
minPixelValue: imageFrame.smallestPixelValue,
|
|
313
|
-
maxPixelValue: imageFrame.largestPixelValue,
|
|
314
|
-
render: undefined, // set below
|
|
315
|
-
rowPixelSpacing: (pixelSpacing as number[])[0]
|
|
316
|
-
? (pixelSpacing as number[])[0]
|
|
317
|
-
: (pixelSpacing as number), // check for specific spacing value
|
|
318
|
-
rows: imageFrame.rows,
|
|
319
|
-
sizeInBytes: getSizeInBytes(),
|
|
320
|
-
slope: (rescaleSlope as number) ? (rescaleSlope as number) : 1,
|
|
321
|
-
width: imageFrame.columns,
|
|
322
|
-
windowCenter: windowCenter as number,
|
|
323
|
-
windowWidth: windowWidth as number,
|
|
324
|
-
decodeTimeInMS: undefined, // TODO
|
|
325
|
-
loadTimeInMS: undefined // TODO
|
|
326
|
-
};
|
|
327
|
-
// add function to return pixel data
|
|
328
|
-
image.getPixelData = function () {
|
|
329
|
-
if (imageFrame.pixelData === undefined) {
|
|
330
|
-
throw new Error("No pixel data for image " + imageId);
|
|
331
|
-
}
|
|
332
|
-
return Array.from(imageFrame.pixelData);
|
|
333
|
-
};
|
|
334
|
-
|
|
335
|
-
// convert color space if not isJPEGBaseline8BitColor
|
|
336
|
-
let isJPEGBaseline8BitColor =
|
|
337
|
-
cornerstoneDICOMImageLoader.isJPEGBaseline8BitColor(
|
|
338
|
-
imageFrame,
|
|
339
|
-
transferSyntax
|
|
340
|
-
);
|
|
341
|
-
|
|
342
|
-
if (image.color && !isJPEGBaseline8BitColor) {
|
|
343
|
-
// setup the canvas context
|
|
344
|
-
canvas.height = imageFrame.rows;
|
|
345
|
-
canvas.width = imageFrame.columns;
|
|
346
|
-
|
|
347
|
-
let context = canvas.getContext("2d");
|
|
348
|
-
|
|
349
|
-
if (!context) {
|
|
350
|
-
throw new Error("Unable to get canvas context");
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
let imageData = context.createImageData(
|
|
354
|
-
imageFrame.columns,
|
|
355
|
-
imageFrame.rows
|
|
356
|
-
);
|
|
357
|
-
|
|
358
|
-
cornerstoneDICOMImageLoader.convertColorSpace(imageFrame, imageData);
|
|
359
|
-
|
|
360
|
-
imageFrame.imageData = imageData;
|
|
361
|
-
imageFrame.pixelData = imageData.data;
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
// Setup the renderer
|
|
365
|
-
if (image.color) {
|
|
366
|
-
image.getCanvas = function () {
|
|
367
|
-
canvas.height = image.rows || 0;
|
|
368
|
-
canvas.width = image.columns || 0;
|
|
369
|
-
let context = canvas.getContext("2d");
|
|
370
|
-
if (!context) {
|
|
371
|
-
throw new Error("Unable to get canvas context");
|
|
372
|
-
}
|
|
373
|
-
context.putImageData(imageFrame.imageData!, 0, 0);
|
|
374
|
-
return canvas;
|
|
375
|
-
};
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
// calculate min/max if not supplied
|
|
379
|
-
if (
|
|
380
|
-
image.minPixelValue === undefined ||
|
|
381
|
-
image.maxPixelValue === undefined
|
|
382
|
-
) {
|
|
383
|
-
let minMax = cornerstoneDICOMImageLoader.getMinMax(pixelData);
|
|
384
|
-
image.minPixelValue = minMax.min;
|
|
385
|
-
image.maxPixelValue = minMax.max;
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
// set the ww/wc to cover the dynamic range of the image if no values are supplied
|
|
389
|
-
if (image.windowCenter === undefined || image.windowWidth === undefined) {
|
|
390
|
-
if (image.color) {
|
|
391
|
-
image.windowWidth = 255;
|
|
392
|
-
image.windowCenter = 128;
|
|
393
|
-
} else if (
|
|
394
|
-
image.maxPixelValue &&
|
|
395
|
-
image.minPixelValue &&
|
|
396
|
-
image.slope &&
|
|
397
|
-
image.intercept
|
|
398
|
-
) {
|
|
399
|
-
let maxVoi = image.maxPixelValue * image.slope + image.intercept;
|
|
400
|
-
let minVoi = image.minPixelValue * image.slope + image.intercept;
|
|
401
|
-
image.windowWidth = maxVoi - minVoi;
|
|
402
|
-
image.windowCenter = (maxVoi + minVoi) / 2;
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
resolve(image as Image);
|
|
407
|
-
}, reject);
|
|
408
|
-
});
|
|
409
|
-
|
|
410
|
-
// Return an object containing the Promise to cornerstone so it can setup callbacks to be
|
|
411
|
-
// invoked asynchronously for the success/resolve and failure/reject scenarios.
|
|
412
|
-
return {
|
|
413
|
-
promise
|
|
414
|
-
};
|
|
415
|
-
};
|
|
416
|
-
|
|
417
|
-
/**
|
|
418
|
-
* This is an override of the cornerstoneDICOMImageLoader setPixelDataType function
|
|
419
|
-
* @instance
|
|
420
|
-
* @function setPixelDataType
|
|
421
|
-
* @param {Object} imageFrame The Id of the image
|
|
422
|
-
*/
|
|
423
|
-
const setPixelDataType = function (imageFrame: ImageFrame) {
|
|
424
|
-
if (imageFrame.bitsAllocated === 16) {
|
|
425
|
-
if (imageFrame.pixelRepresentation === 0) {
|
|
426
|
-
imageFrame.pixelData = new Uint16Array(
|
|
427
|
-
imageFrame.pixelData as Uint16Array
|
|
428
|
-
);
|
|
429
|
-
} else {
|
|
430
|
-
imageFrame.pixelData = new Int16Array(imageFrame.pixelData as Int16Array);
|
|
431
|
-
}
|
|
432
|
-
} else {
|
|
433
|
-
imageFrame.pixelData = new Uint8Array(imageFrame.pixelData as Uint8Array);
|
|
434
|
-
}
|
|
435
|
-
};
|