-
Notifications
You must be signed in to change notification settings - Fork 83
/
Copy pathgetImageData.js
158 lines (135 loc) · 4.63 KB
/
getImageData.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
import { vec3 } from 'gl-matrix';
import vtkImageData from 'vtk.js/Sources/Common/DataModel/ImageData';
import vtkDataArray from 'vtk.js/Sources/Common/Core/DataArray';
import vtkMath from 'vtk.js/Sources/Common/Core/Math';
import buildMetadata from './data/buildMetadata.js';
import imageDataCache from './data/imageDataCache.js';
import sortDatasetsByImagePosition from './data/sortDatasetsByImagePosition.js';
//Tolerance for ImageOrientationPatient
const iopTolerance = 1e-6;
export default function getImageData(imageIds, displaySetInstanceUid) {
const cachedImageDataObject = imageDataCache.get(displaySetInstanceUid);
if (cachedImageDataObject) {
return cachedImageDataObject;
}
const { metaData0, metaDataMap, imageMetaData0 } = buildMetadata(imageIds);
let { rowCosines, columnCosines } = metaData0;
//correct for the 32bit float header issue before orthogonalizing
//https://github.com/OHIF/Viewers/issues/2847
for (let i = 0; i < rowCosines.length; i++) {
if (Math.abs(rowCosines[i]) < iopTolerance) {
rowCosines[i] = 0;
}
if (Math.abs(columnCosines[i]) < iopTolerance) {
columnCosines[i] = 0;
}
}
const rowCosineVec = vec3.fromValues(...rowCosines);
const colCosineVec = vec3.fromValues(...columnCosines);
const scanAxisNormal = vec3.cross([], rowCosineVec, colCosineVec);
//setDirection expects orthogonal matrix
let direction = [];
vtkMath.orthogonalize3x3(
[rowCosineVec, colCosineVec, scanAxisNormal],
direction
);
const { spacing, origin, sortedDatasets } = sortDatasetsByImagePosition(
scanAxisNormal,
metaDataMap
);
const xSpacing = metaData0.columnPixelSpacing;
const ySpacing = metaData0.rowPixelSpacing;
const zSpacing = spacing;
const xVoxels = metaData0.columns;
const yVoxels = metaData0.rows;
const zVoxels = metaDataMap.size;
const signed = imageMetaData0.pixelRepresentation === 1;
const multiComponent = metaData0.numberOfComponents > 1;
// TODO: Support numberOfComponents = 3 for RGB?
if (multiComponent) {
throw new Error('Multi component image not supported by this plugin.');
}
let pixelArray;
switch (imageMetaData0.bitsAllocated) {
case 8:
if (signed) {
throw new Error(
'8 Bit signed images are not yet supported by this plugin.'
);
} else {
throw new Error(
'8 Bit unsigned images are not yet supported by this plugin.'
);
}
case 16:
pixelArray = new Float32Array(xVoxels * yVoxels * zVoxels);
break;
}
const scalarArray = vtkDataArray.newInstance({
name: 'Pixels',
numberOfComponents: 1,
values: pixelArray,
});
const imageData = vtkImageData.newInstance();
imageData.setDimensions(xVoxels, yVoxels, zVoxels);
imageData.setSpacing(xSpacing, ySpacing, zSpacing);
imageData.setDirection(direction);
imageData.setOrigin(...origin);
imageData.getPointData().setScalars(scalarArray);
const _publishPixelDataInserted = count => {
imageDataObject.subscriptions.onPixelDataInserted.forEach(callback => {
callback(count);
});
};
const _publishPixelDataInsertedError = error => {
imageDataObject.subscriptions.onPixelDataInsertedError.forEach(callback => {
callback(error);
});
};
const _publishAllPixelDataInserted = () => {
imageDataObject.subscriptions.onAllPixelDataInserted.forEach(callback => {
callback();
});
imageDataObject.isLoading = false;
imageDataObject.loaded = true;
imageDataObject.vtkImageData.modified();
// Remove all subscriptions on completion.
imageDataObject.subscriptions = {
onPixelDataInserted: [],
onPixelDataInsertedError: [],
onAllPixelDataInserted: [],
};
};
const imageDataObject = {
imageIds,
metaData0,
imageMetaData0,
dimensions: [xVoxels, yVoxels, zVoxels],
spacing: [xSpacing, ySpacing, zSpacing],
origin,
direction,
vtkImageData: imageData,
metaDataMap,
sortedDatasets,
loaded: false,
subscriptions: {
onPixelDataInserted: [],
onPixelDataInsertedError: [],
onAllPixelDataInserted: [],
},
onPixelDataInserted: callback => {
imageDataObject.subscriptions.onPixelDataInserted.push(callback);
},
onPixelDataInsertedError: callback => {
imageDataObject.subscriptions.onPixelDataInsertedError.push(callback);
},
onAllPixelDataInserted: callback => {
imageDataObject.subscriptions.onAllPixelDataInserted.push(callback);
},
_publishPixelDataInserted,
_publishAllPixelDataInserted,
_publishPixelDataInsertedError,
};
imageDataCache.set(displaySetInstanceUid, imageDataObject);
return imageDataObject;
}