-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathdecodePixelData.js
117 lines (110 loc) · 4.06 KB
/
decodePixelData.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
const dcmjsImaging = require('dcmjs-imaging');
// Mimics a class not exported by dcmjs-imaging
const pixelShim = (
width,
height,
bitsAllocated,
bitsStored,
samplesPerPixel,
pixelRepresentation,
planarConfiguration,
photometricInterpretation
) => ({
getWidth: () => width,
getHeight: () => height,
getBitsAllocated: () => bitsAllocated,
getBitsStored: () => bitsStored,
getSamplesPerPixel: () => samplesPerPixel,
getPixelRepresentation: () => pixelRepresentation,
getPlanarConfiguration: () => planarConfiguration,
getPhotometricInterpretation: () => photometricInterpretation,
});
/**
* Decodes frame pixel data.
* @param {Object} dataset - The DICOM dataset object.
* @param {string} transferSyntaxUid - The dataset transfer syntax UID.
* @param {number} frame - The frame index.
* @returns {Uint8Array} The decoded frame pixel data.
*/
const decodePixelData = (dataset, transferSyntaxUid, frame) => {
if (frame < 0 || frame >= dataset.NumberOfFrames) {
throw new Error(`Requested frame is out of range [${frame}]`);
}
if (!dataset.PixelData) {
throw new Error('Could not extract pixel data');
}
if (!dataset.Columns || !dataset.Rows) {
throw new Error(
`Width/height has an invalid value [w: ${dataset.Columns}, h: ${dataset.Rows}]`
);
}
if (!dataset.BitsAllocated || !dataset.BitsStored) {
throw new Error(
`Bits allocated/stored has an invalid value [allocated: ${dataset.BitsAllocated}, stored: ${dataset.BitsStored}]`
);
}
if (!dataset.PhotometricInterpretation) {
throw new Error(
`Photometric interpretation has an invalid value [${dataset.PhotometricInterpretation}]`
);
}
const pixelBuffers = dataset.PixelData;
if (
transferSyntaxUid === '1.2.840.10008.1.2' || // ImplicitVRLittleEndian
transferSyntaxUid === '1.2.840.10008.1.2.1' || // ExplicitVRLittleEndian
transferSyntaxUid === '1.2.840.10008.1.2.1.99' // DeflatedExplicitVRLittleEndian
) {
const frameSize =
dataset.Rows * dataset.Columns * dataset.SamplesPerPixel * ((dataset.BitsAllocated + 7) / 8);
const frameOffset = frameSize * frame;
const pixelBuffer = new Uint8Array(
Array.isArray(pixelBuffers) ? pixelBuffers.find((o) => o) : pixelBuffers
);
const framePixelBuffer = pixelBuffer.slice(frameOffset, frameOffset + frameSize);
return framePixelBuffer;
} else {
const frameFragmentsData = new Uint8Array(pixelBuffers[frame]);
const pixel = pixelShim(
dataset.Columns,
dataset.Rows,
dataset.BitsAllocated,
dataset.BitsStored,
dataset.SamplesPerPixel,
dataset.PixelRepresentation,
dataset.PlanarConfiguration,
dataset.PhotometricInterpretation
);
if (transferSyntaxUid === '1.2.840.10008.1.2.5') {
// RleLossless
return dcmjsImaging.NativePixelDecoder.decodeRle(pixel, frameFragmentsData);
} else if (
// JpegBaselineProcess1, JpegBaselineProcess2_4
transferSyntaxUid === '1.2.840.10008.1.2.4.50' ||
transferSyntaxUid === '1.2.840.10008.1.2.4.51'
) {
return dcmjsImaging.NativePixelDecoder.decodeJpeg(pixel, frameFragmentsData, {
convertColorspaceToRgb: true,
});
} else if (
// JpegLosslessProcess14, JpegLosslessProcess14V1
transferSyntaxUid === '1.2.840.10008.1.2.4.57' ||
transferSyntaxUid === '1.2.840.10008.1.2.4.70'
) {
return dcmjsImaging.NativePixelDecoder.decodeJpeg(pixel, frameFragmentsData);
} else if (
// JpegLsLossless, JpegLsLossy
transferSyntaxUid === '1.2.840.10008.1.2.4.80' ||
transferSyntaxUid === '1.2.840.10008.1.2.4.81'
) {
return dcmjsImaging.NativePixelDecoder.decodeJpegLs(pixel, frameFragmentsData);
} else if (
// Jpeg2000Lossless, Jpeg2000Lossy
transferSyntaxUid === '1.2.840.10008.1.2.4.90' ||
transferSyntaxUid === '1.2.840.10008.1.2.4.91'
) {
return dcmjsImaging.NativePixelDecoder.decodeJpeg2000(pixel, frameFragmentsData);
}
throw new Error(`Transfer syntax cannot be currently decoded [${transferSyntaxUid}]`);
}
};
module.exports = decodePixelData;