@cornerstonejs/adapters 5.4.10 → 5.4.12

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.
@@ -0,0 +1,17 @@
1
+ export function getReferencedFrameNumber(imageId: string, metadata: object): number | undefined;
2
+ export function getReferencedSourceImageSequenceItem(image: {
3
+ imageId?: string;
4
+ }, metadata: object): {
5
+ ReferencedSOPInstanceUID: string;
6
+ ReferencedFrameNumber?: number;
7
+ };
8
+ export function normalizeSharedFunctionalGroupsSequence(dataset: any): void;
9
+ export function applyPerFrameFunctionalGroups(dataset: object, frames: Array<{
10
+ referencedSegmentNumber?: number;
11
+ sourceImageSequenceItem: {
12
+ ReferencedSOPInstanceUID: string;
13
+ ReferencedFrameNumber?: number;
14
+ };
15
+ planeOrientationSequence?: object;
16
+ planePositionSequence?: object;
17
+ }>): void;
@@ -0,0 +1,116 @@
1
+ import _defineProperty from '@babel/runtime/helpers/defineProperty';
2
+ import _objectWithoutProperties from '@babel/runtime/helpers/objectWithoutProperties';
3
+ import { Enums, utilities } from '@cornerstonejs/core';
4
+
5
+ const _excluded = ["SegmentIdentificationSequence"];
6
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
7
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
8
+ const MetadataModules = Enums.MetadataModules;
9
+
10
+ /**
11
+ * Resolves the 1-based DICOM frame number referenced by an imageId.
12
+ *
13
+ * Prefer the metadata provider's own frame extraction when it offers one — it
14
+ * understands the full set of imageId shapes the host app produces (wadors
15
+ * `/frames/N` as well as `?frame=N` / `&frame=N`). Fall back to the core
16
+ * FrameRange helper (handles `/frames/N` and `frameNumber=N`) so that
17
+ * provider-agnostic callers still resolve multi-frame references. A one-off
18
+ * `/[?&]frame=/` regex silently drops the wadors form, so it must not be used.
19
+ *
20
+ * @param {string} imageId
21
+ * @param {object} metadata - metadata provider
22
+ * @returns {number|undefined}
23
+ */
24
+ function getReferencedFrameNumber(imageId, metadata) {
25
+ var _metadata$getFrameInf;
26
+ if (!imageId) {
27
+ return undefined;
28
+ }
29
+ const providerFrame = metadata === null || metadata === void 0 || (_metadata$getFrameInf = metadata.getFrameInformationFromURL) === null || _metadata$getFrameInf === void 0 ? void 0 : _metadata$getFrameInf.call(metadata, imageId);
30
+ const frameNumber = providerFrame != null ? Number(providerFrame) : utilities.FrameRange.imageIdToFrameStart(imageId);
31
+ return Number.isFinite(frameNumber) ? frameNumber : undefined;
32
+ }
33
+
34
+ /**
35
+ * Builds a SourceImageSequence item (ReferencedSOPInstanceUID + optional
36
+ * ReferencedFrameNumber) for a cornerstone image, using the shared frame
37
+ * extraction so all SEG export paths resolve multi-frame references identically.
38
+ *
39
+ * @param {{ imageId?: string }} image
40
+ * @param {object} metadata - metadata provider
41
+ * @returns {{ ReferencedSOPInstanceUID: string, ReferencedFrameNumber?: number }}
42
+ */
43
+ function getReferencedSourceImageSequenceItem(image, metadata) {
44
+ var _metadata$get;
45
+ const imageData = (metadata === null || metadata === void 0 || (_metadata$get = metadata.get) === null || _metadata$get === void 0 ? void 0 : _metadata$get.call(metadata, MetadataModules.IMAGE_DATA, image === null || image === void 0 ? void 0 : image.imageId)) || {};
46
+ const referencedFrameNumber = getReferencedFrameNumber(image === null || image === void 0 ? void 0 : image.imageId, metadata);
47
+ const item = {
48
+ ReferencedSOPInstanceUID: imageData.SOPInstanceUID
49
+ };
50
+ if (Number.isFinite(referencedFrameNumber) && referencedFrameNumber > 0) {
51
+ item.ReferencedFrameNumber = referencedFrameNumber;
52
+ }
53
+ return item;
54
+ }
55
+ function normalizeSharedFunctionalGroupsSequence(dataset) {
56
+ const shared = dataset.SharedFunctionalGroupsSequence;
57
+ if (Array.isArray(shared) && shared.length > 0) {
58
+ dataset.SharedFunctionalGroupsSequence = shared[0];
59
+ } else if (!shared || typeof shared !== 'object') {
60
+ dataset.SharedFunctionalGroupsSequence = {};
61
+ }
62
+ }
63
+
64
+ /**
65
+ * @param {object} dataset - SEG dataset
66
+ * @param {Array<{
67
+ * referencedSegmentNumber?: number,
68
+ * sourceImageSequenceItem: { ReferencedSOPInstanceUID: string, ReferencedFrameNumber?: number },
69
+ * planeOrientationSequence?: object,
70
+ * planePositionSequence?: object,
71
+ * }>} frames
72
+ *
73
+ * `referencedSegmentNumber` drives the per-frame `SegmentIdentificationSequence`
74
+ * macro (one segment per frame — BINARY SEGs). Omit it for LABELMAP SEGs: there a
75
+ * single frame carries many segment labels as pixel values, so the standard
76
+ * forbids the macro and a fixed `ReferencedSegmentNumber` would be wrong for any
77
+ * label other than the one hard-coded.
78
+ */
79
+ function applyPerFrameFunctionalGroups(dataset, frames) {
80
+ normalizeSharedFunctionalGroupsSequence(dataset);
81
+ const validFrames = frames.filter(frame => {
82
+ var _frame$sourceImageSeq;
83
+ return frame === null || frame === void 0 || (_frame$sourceImageSeq = frame.sourceImageSequenceItem) === null || _frame$sourceImageSeq === void 0 ? void 0 : _frame$sourceImageSeq.ReferencedSOPInstanceUID;
84
+ });
85
+ const existing = dataset.PerFrameFunctionalGroupsSequence;
86
+ const existingList = Array.isArray(existing) ? existing : [];
87
+ const nextSequence = validFrames.map((frame, index) => {
88
+ const prior = existingList[index] && typeof existingList[index] === 'object' ? existingList[index] : {};
89
+
90
+ // Drop any inherited SegmentIdentificationSequence when this frame has no
91
+ // referencedSegmentNumber (LABELMAP path) so the macro is truly absent.
92
+ prior.SegmentIdentificationSequence;
93
+ const priorRest = _objectWithoutProperties(prior, _excluded);
94
+ const group = _objectSpread(_objectSpread({}, priorRest), {}, {
95
+ DerivationImageSequence: [{
96
+ SourceImageSequence: [frame.sourceImageSequenceItem]
97
+ }]
98
+ });
99
+ if (frame.referencedSegmentNumber != null) {
100
+ group.SegmentIdentificationSequence = {
101
+ ReferencedSegmentNumber: frame.referencedSegmentNumber
102
+ };
103
+ }
104
+ if (frame.planeOrientationSequence) {
105
+ group.PlaneOrientationSequence = frame.planeOrientationSequence;
106
+ }
107
+ if (frame.planePositionSequence) {
108
+ group.PlanePositionSequence = frame.planePositionSequence;
109
+ }
110
+ return group;
111
+ });
112
+ dataset.PerFrameFunctionalGroupsSequence = nextSequence;
113
+ dataset.NumberOfFrames = nextSequence.length;
114
+ }
115
+
116
+ export { applyPerFrameFunctionalGroups, getReferencedFrameNumber, getReferencedSourceImageSequenceItem, normalizeSharedFunctionalGroupsSequence };
@@ -0,0 +1,46 @@
1
+ declare const RLE_LOSSLESS_TRANSFER_SYNTAX_UID = "1.2.840.10008.1.2.5";
2
+ declare const EXPLICIT_VR_LITTLE_ENDIAN_TRANSFER_SYNTAX_UID: any;
3
+ declare function getSegNumberOfFramesFromDataset(multiframe: Record<string, unknown>): number;
4
+ declare function decodeSegFramesFromMultiframe(multiframe: Record<string, unknown>): ArrayLike<number>[];
5
+ declare function createDecodeImageDataFromMultiframe(multiframe: Record<string, unknown>): (_frameImageId: string, frameNumber: number) => Promise<ArrayLike<number>>;
6
+ declare function unpackBinaryFrameFromPacked(packed: Uint8Array, samplesPerFrame: number): Uint8Array;
7
+ declare function getBitmapFramesFromDataset(dataset: {
8
+ NumberOfFrames?: number | string;
9
+ Rows?: number | string;
10
+ Columns?: number | string;
11
+ BitsAllocated?: number | string;
12
+ PixelData?: unknown;
13
+ }): {
14
+ frames: Uint8Array[];
15
+ bitsAllocated: number;
16
+ } | {
17
+ frames: Uint16Array[];
18
+ bitsAllocated: number;
19
+ };
20
+ declare function packBits(samples: ArrayLike<number>, rowLength?: number): Uint8Array;
21
+ declare function bitPackBinaryFrame(frame: ArrayLike<number>): Uint8Array;
22
+ declare function encodeFrameToRle(frame: ArrayLike<number>, bitsAllocated: number, columns?: number): ArrayBufferLike;
23
+ export declare function isUncompressedSegTransferSyntax(transferSyntaxUID: string): boolean;
24
+ type EncodeFramesToTransferSyntaxArgs = {
25
+ transferSyntaxUID: string;
26
+ bitsAllocated: number;
27
+ columns?: number;
28
+ } & ({
29
+ frames: ArrayLike<number>[];
30
+ buildFrame?: never;
31
+ frameCount?: never;
32
+ } | {
33
+ frames?: never;
34
+ buildFrame: (frameIndex: number) => ArrayLike<number>;
35
+ frameCount: number;
36
+ });
37
+ export declare function encodeFramesToTransferSyntax(args: EncodeFramesToTransferSyntaxArgs): {
38
+ transferSyntaxUID: string;
39
+ pixelDataVR: string;
40
+ pixelData: Uint8Array | Uint16Array;
41
+ } | {
42
+ transferSyntaxUID: string;
43
+ pixelDataVR: string;
44
+ pixelData: ArrayBuffer[];
45
+ };
46
+ export { RLE_LOSSLESS_TRANSFER_SYNTAX_UID, EXPLICIT_VR_LITTLE_ENDIAN_TRANSFER_SYNTAX_UID, getBitmapFramesFromDataset, bitPackBinaryFrame, unpackBinaryFrameFromPacked, decodeSegFramesFromMultiframe, createDecodeImageDataFromMultiframe, getSegNumberOfFramesFromDataset, packBits, encodeFrameToRle, };
@@ -0,0 +1,440 @@
1
+ import { constants } from 'dcmjs';
2
+
3
+ const RLE_LOSSLESS_TRANSFER_SYNTAX_UID = '1.2.840.10008.1.2.5';
4
+ const EXPLICIT_VR_LITTLE_ENDIAN_TRANSFER_SYNTAX_UID = constants.EXPLICIT_LITTLE_ENDIAN;
5
+ function getTransferSyntaxUid(multiframe) {
6
+ var _meta$TransferSyntaxU;
7
+ const meta = multiframe._meta;
8
+ const fromMeta = meta === null || meta === void 0 || (_meta$TransferSyntaxU = meta.TransferSyntaxUID) === null || _meta$TransferSyntaxU === void 0 || (_meta$TransferSyntaxU = _meta$TransferSyntaxU.Value) === null || _meta$TransferSyntaxU === void 0 ? void 0 : _meta$TransferSyntaxU[0];
9
+ if (fromMeta) {
10
+ return fromMeta;
11
+ }
12
+ if (typeof multiframe.TransferSyntaxUID === 'string') {
13
+ return multiframe.TransferSyntaxUID;
14
+ }
15
+ return EXPLICIT_VR_LITTLE_ENDIAN_TRANSFER_SYNTAX_UID;
16
+ }
17
+ function getSegNumberOfFramesFromDataset(multiframe) {
18
+ const fromTag = Number(multiframe.NumberOfFrames);
19
+ if (fromTag > 0) {
20
+ return fromTag;
21
+ }
22
+ const perFrame = multiframe.PerFrameFunctionalGroupsSequence;
23
+ if (Array.isArray(perFrame) && perFrame.length > 0) {
24
+ return perFrame.length;
25
+ }
26
+ return 1;
27
+ }
28
+ function decodeRlePackBitsSegment(data, start, end, outLength) {
29
+ const out = new Uint8Array(outLength);
30
+ let outIndex = 0;
31
+ let inIndex = start;
32
+ while (inIndex < end && outIndex < outLength) {
33
+ const n = data[inIndex++];
34
+ if (n >= 0 && n <= 127) {
35
+ for (let i = 0; i < n + 1 && outIndex < outLength; ++i) {
36
+ out[outIndex++] = data[inIndex++] & 0xff;
37
+ }
38
+ } else if (n <= -1 && n >= -127) {
39
+ const value = data[inIndex++] & 0xff;
40
+ for (let j = 0; j < -n + 1 && outIndex < outLength; ++j) {
41
+ out[outIndex++] = value;
42
+ }
43
+ }
44
+ }
45
+ return out;
46
+ }
47
+ function decodeRleLosslessToPackedBytes(rleData, packedByteLength) {
48
+ const frameData = rleData instanceof Uint8Array ? rleData : new Uint8Array(rleData);
49
+ const header = new DataView(frameData.buffer, frameData.byteOffset, frameData.byteLength);
50
+ const data = new Int8Array(frameData.buffer, frameData.byteOffset, frameData.byteLength);
51
+ const numSegments = header.getInt32(0, true);
52
+ if (numSegments !== 1) {
53
+ throw new Error("Expected a single RLE segment for SEG re-encode, got ".concat(numSegments));
54
+ }
55
+ const start = header.getInt32(4, true);
56
+ let end = header.getInt32(8, true);
57
+ if (end === 0) {
58
+ end = frameData.length;
59
+ }
60
+ return decodeRlePackBitsSegment(data, start, end, packedByteLength);
61
+ }
62
+ function decodeRleMultiByteFrame(rleData, samplesPerFrame, bitsAllocated) {
63
+ const frameData = rleData instanceof Uint8Array ? rleData : new Uint8Array(rleData);
64
+ const header = new DataView(frameData.buffer, frameData.byteOffset, frameData.byteLength);
65
+ const data = new Int8Array(frameData.buffer, frameData.byteOffset, frameData.byteLength);
66
+ const numSegments = header.getInt32(0, true);
67
+ const bytesPerSample = Math.ceil(bitsAllocated / 8);
68
+ if (numSegments !== bytesPerSample) {
69
+ throw new Error("Expected ".concat(bytesPerSample, " RLE segment(s) for ").concat(bitsAllocated, "-bit SEG, got ").concat(numSegments));
70
+ }
71
+ const segmentStart = index => header.getInt32(4 + index * 4, true);
72
+ if (bitsAllocated <= 8) {
73
+ return decodeRlePackBitsSegment(data, segmentStart(0), frameData.length, samplesPerFrame);
74
+ }
75
+ const highStart = segmentStart(0);
76
+ const lowStart = segmentStart(1);
77
+ const highBytes = decodeRlePackBitsSegment(data, highStart, lowStart, samplesPerFrame);
78
+ const lowBytes = decodeRlePackBitsSegment(data, lowStart, frameData.length, samplesPerFrame);
79
+ const frame = new Uint16Array(samplesPerFrame);
80
+ for (let i = 0; i < samplesPerFrame; i++) {
81
+ frame[i] = (highBytes[i] << 8 | lowBytes[i]) & 0xffff;
82
+ }
83
+ return frame;
84
+ }
85
+ function decodeSegFramesFromMultiframe(multiframe) {
86
+ const rows = Number(multiframe.Rows);
87
+ const columns = Number(multiframe.Columns);
88
+ const samplesPerFrame = rows * columns;
89
+ const bitsAllocated = Number(multiframe.BitsAllocated);
90
+ const numberOfFrames = getSegNumberOfFramesFromDataset(multiframe);
91
+ const transferSyntaxUid = getTransferSyntaxUid(multiframe);
92
+ if (!multiframe.PixelData) {
93
+ throw new Error('SEG dataset has no PixelData');
94
+ }
95
+ if (bitsAllocated === 1) {
96
+ if (transferSyntaxUid === RLE_LOSSLESS_TRANSFER_SYNTAX_UID) {
97
+ const encodedFrames = Array.isArray(multiframe.PixelData) ? multiframe.PixelData : [multiframe.PixelData];
98
+ const bytesPerFrame = getBytesForBinaryFrame(samplesPerFrame);
99
+ const frames = [];
100
+ for (let frameIndex = 0; frameIndex < numberOfFrames; frameIndex++) {
101
+ const rleFrame = encodedFrames[frameIndex];
102
+ if (!rleFrame) {
103
+ frames.push(new Uint8Array(samplesPerFrame));
104
+ continue;
105
+ }
106
+ const packed = decodeRleLosslessToPackedBytes(rleFrame, bytesPerFrame);
107
+ frames.push(unpackBinaryFrameFromPacked(packed, samplesPerFrame));
108
+ }
109
+ return frames;
110
+ }
111
+ return getBitmapFramesFromDataset(multiframe).frames;
112
+ }
113
+ if (transferSyntaxUid === RLE_LOSSLESS_TRANSFER_SYNTAX_UID) {
114
+ const encodedFrames = Array.isArray(multiframe.PixelData) ? multiframe.PixelData : [multiframe.PixelData];
115
+ const frames = [];
116
+ for (let frameIndex = 0; frameIndex < numberOfFrames; frameIndex++) {
117
+ const rleFrame = encodedFrames[frameIndex];
118
+ if (!rleFrame) {
119
+ frames.push(bitsAllocated <= 8 ? new Uint8Array(samplesPerFrame) : new Uint16Array(samplesPerFrame));
120
+ continue;
121
+ }
122
+ frames.push(decodeRleMultiByteFrame(rleFrame, samplesPerFrame, bitsAllocated));
123
+ }
124
+ return frames;
125
+ }
126
+ return getBitmapFramesFromDataset(multiframe).frames;
127
+ }
128
+ function createDecodeImageDataFromMultiframe(multiframe) {
129
+ let cachedFrames = null;
130
+ return async (_frameImageId, frameNumber) => {
131
+ if (!cachedFrames) {
132
+ cachedFrames = decodeSegFramesFromMultiframe(multiframe);
133
+ }
134
+ const frame = cachedFrames[frameNumber - 1];
135
+ if (!frame) {
136
+ throw new Error("No SEG frame at index ".concat(frameNumber));
137
+ }
138
+ return frame;
139
+ };
140
+ }
141
+ function getBytesForBinaryFrame(numPixels) {
142
+ return Math.ceil(numPixels / 8);
143
+ }
144
+ function asUint8PixelData(pixelData) {
145
+ if (pixelData instanceof Uint8Array) {
146
+ return pixelData;
147
+ }
148
+ if (pixelData instanceof ArrayBuffer) {
149
+ return new Uint8Array(pixelData);
150
+ }
151
+ if (Array.isArray(pixelData)) {
152
+ if (pixelData.length === 1) {
153
+ return new Uint8Array(pixelData[0]);
154
+ }
155
+ throw new Error('Multiframe encapsulated PixelData fragments cannot be converted to binary frames for re-encoding');
156
+ }
157
+ return new Uint8Array(pixelData);
158
+ }
159
+ function normalizeBinaryFrameTo01(frame) {
160
+ const normalized = new Uint8Array(frame.length);
161
+ for (let i = 0; i < frame.length; i++) {
162
+ normalized[i] = frame[i] ? 1 : 0;
163
+ }
164
+ return normalized;
165
+ }
166
+ function unpackBinaryFrameFromPacked(packed, samplesPerFrame) {
167
+ const frame = new Uint8Array(samplesPerFrame);
168
+ for (let i = 0; i < samplesPerFrame; i++) {
169
+ const bytePos = i >> 3;
170
+ const bitPos = i % 8;
171
+ frame[i] = packed[bytePos] & 1 << bitPos ? 1 : 0;
172
+ }
173
+ return frame;
174
+ }
175
+ function unpackBinaryFrameFromContinuousPack(packed, samplesPerFrame, frameIndex) {
176
+ const frame = new Uint8Array(samplesPerFrame);
177
+ const bitOffset = frameIndex * samplesPerFrame;
178
+ for (let i = 0; i < samplesPerFrame; i++) {
179
+ const bitIndex = bitOffset + i;
180
+ const bytePos = bitIndex >> 3;
181
+ const bitPos = bitIndex % 8;
182
+ frame[i] = packed[bytePos] & 1 << bitPos ? 1 : 0;
183
+ }
184
+ return frame;
185
+ }
186
+ function getBitmapFramesFromDataset(dataset) {
187
+ const numberOfFrames = Number(dataset.NumberOfFrames) || 1;
188
+ const rows = Number(dataset.Rows);
189
+ const columns = Number(dataset.Columns);
190
+ const samplesPerFrame = rows * columns;
191
+ const bitsAllocated = Number(dataset.BitsAllocated);
192
+ if (!dataset.PixelData) {
193
+ throw new Error('Bitmap SEG dataset has no PixelData');
194
+ }
195
+ if (bitsAllocated === 1) {
196
+ const buffer = asUint8PixelData(dataset.PixelData);
197
+ const bytesPerFrame = getBytesForBinaryFrame(samplesPerFrame);
198
+ const unpackedFrameBytes = samplesPerFrame * numberOfFrames;
199
+ const perFramePackedBytes = bytesPerFrame * numberOfFrames;
200
+ const continuousPackedBytes = getBytesForBinaryFrame(samplesPerFrame * numberOfFrames);
201
+ const frames = [];
202
+ if (buffer.length === unpackedFrameBytes) {
203
+ for (let frameIndex = 0; frameIndex < numberOfFrames; frameIndex++) {
204
+ const start = frameIndex * samplesPerFrame;
205
+ frames.push(normalizeBinaryFrameTo01(buffer.subarray(start, start + samplesPerFrame)));
206
+ }
207
+ } else if (buffer.length === perFramePackedBytes) {
208
+ for (let frameIndex = 0; frameIndex < numberOfFrames; frameIndex++) {
209
+ const framePacked = buffer.subarray(frameIndex * bytesPerFrame, (frameIndex + 1) * bytesPerFrame);
210
+ frames.push(unpackBinaryFrameFromPacked(framePacked, samplesPerFrame));
211
+ }
212
+ } else if (buffer.length === continuousPackedBytes) {
213
+ for (let frameIndex = 0; frameIndex < numberOfFrames; frameIndex++) {
214
+ frames.push(unpackBinaryFrameFromContinuousPack(buffer, samplesPerFrame, frameIndex));
215
+ }
216
+ } else {
217
+ throw new Error("Unexpected 1-bit SEG PixelData length ".concat(buffer.length, " for ").concat(numberOfFrames, " frame(s) of ").concat(samplesPerFrame, " pixels"));
218
+ }
219
+ return {
220
+ frames,
221
+ bitsAllocated
222
+ };
223
+ }
224
+ if (bitsAllocated <= 8) {
225
+ const buffer = asUint8PixelData(dataset.PixelData);
226
+ const frames = [];
227
+ for (let frameIndex = 0; frameIndex < numberOfFrames; frameIndex++) {
228
+ const start = frameIndex * samplesPerFrame;
229
+ frames.push(buffer.slice(start, start + samplesPerFrame));
230
+ }
231
+ return {
232
+ frames,
233
+ bitsAllocated
234
+ };
235
+ }
236
+ let buffer;
237
+ if (dataset.PixelData instanceof Uint16Array) {
238
+ buffer = dataset.PixelData;
239
+ } else {
240
+ const bytes = asUint8PixelData(dataset.PixelData);
241
+ buffer = new Uint16Array(bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength));
242
+ }
243
+ const frames = [];
244
+ for (let frameIndex = 0; frameIndex < numberOfFrames; frameIndex++) {
245
+ const start = frameIndex * samplesPerFrame;
246
+ frames.push(buffer.slice(start, start + samplesPerFrame));
247
+ }
248
+ return {
249
+ frames,
250
+ bitsAllocated
251
+ };
252
+ }
253
+ function packBitsRange(samples, start, end, output) {
254
+ let i = start;
255
+ while (i < end) {
256
+ let replicateRunLength = 1;
257
+ while (i + replicateRunLength < end && replicateRunLength < 128 && samples[i + replicateRunLength] === samples[i]) {
258
+ replicateRunLength++;
259
+ }
260
+ if (replicateRunLength >= 2) {
261
+ output.push(257 - replicateRunLength, samples[i] & 0xff);
262
+ i += replicateRunLength;
263
+ continue;
264
+ }
265
+ const literalStart = i;
266
+ i++;
267
+ while (i < end) {
268
+ replicateRunLength = 1;
269
+ while (i + replicateRunLength < end && replicateRunLength < 128 && samples[i + replicateRunLength] === samples[i]) {
270
+ replicateRunLength++;
271
+ }
272
+ if (replicateRunLength >= 2 || i - literalStart >= 128) {
273
+ break;
274
+ }
275
+ i++;
276
+ }
277
+ const literalLength = i - literalStart;
278
+ output.push(literalLength - 1);
279
+ for (let j = literalStart; j < i; j++) {
280
+ output.push(samples[j] & 0xff);
281
+ }
282
+ }
283
+ }
284
+ function packBits(samples, rowLength) {
285
+ const output = [];
286
+ const total = samples.length;
287
+ if (rowLength && rowLength > 0 && total % rowLength === 0) {
288
+ for (let start = 0; start < total; start += rowLength) {
289
+ packBitsRange(samples, start, start + rowLength, output);
290
+ }
291
+ } else {
292
+ packBitsRange(samples, 0, total, output);
293
+ }
294
+ return Uint8Array.from(output);
295
+ }
296
+ function bitPackBinaryFrame(frame) {
297
+ const packedLength = Math.ceil(frame.length / 8);
298
+ const packed = new Uint8Array(packedLength);
299
+ for (let i = 0; i < frame.length; i++) {
300
+ if (frame[i]) {
301
+ packed[i >> 3] |= 1 << i % 8;
302
+ }
303
+ }
304
+ return packed;
305
+ }
306
+ function concatUint8Frames(frames) {
307
+ const totalLength = frames.reduce((sum, frame) => sum + frame.length, 0);
308
+ const combined = new Uint8Array(totalLength);
309
+ let offset = 0;
310
+ for (const frame of frames) {
311
+ for (let i = 0; i < frame.length; i++) {
312
+ combined[offset + i] = frame[i] & 0xff;
313
+ }
314
+ offset += frame.length;
315
+ }
316
+ return combined;
317
+ }
318
+ function concatUint16Frames(frames) {
319
+ const totalLength = frames.reduce((sum, frame) => sum + frame.length, 0);
320
+ const combined = new Uint16Array(totalLength);
321
+ let offset = 0;
322
+ for (const frame of frames) {
323
+ for (let i = 0; i < frame.length; i++) {
324
+ combined[offset + i] = frame[i] & 0xffff;
325
+ }
326
+ offset += frame.length;
327
+ }
328
+ return combined;
329
+ }
330
+ function getRleSegmentsForFrame(frame, bitsAllocated) {
331
+ if (bitsAllocated === 1) {
332
+ return [bitPackBinaryFrame(frame)];
333
+ }
334
+ if (bitsAllocated === 8) {
335
+ const segment = new Uint8Array(frame.length);
336
+ for (let i = 0; i < frame.length; i++) {
337
+ segment[i] = frame[i] & 0xff;
338
+ }
339
+ return [segment];
340
+ }
341
+ if (bitsAllocated === 16) {
342
+ const highByteSegment = new Uint8Array(frame.length);
343
+ const lowByteSegment = new Uint8Array(frame.length);
344
+ for (let i = 0; i < frame.length; i++) {
345
+ const sample = frame[i] & 0xffff;
346
+ highByteSegment[i] = sample >> 8 & 0xff;
347
+ lowByteSegment[i] = sample & 0xff;
348
+ }
349
+ return [highByteSegment, lowByteSegment];
350
+ }
351
+ throw new Error("Unsupported bitsAllocated for RLE encoding: ".concat(bitsAllocated, ". Expected 1, 8, or 16."));
352
+ }
353
+ function encodeFrameToRle(frame, bitsAllocated, columns) {
354
+ const segmentPlanes = getRleSegmentsForFrame(frame, bitsAllocated);
355
+ if (segmentPlanes.length > 15) {
356
+ throw new Error("RLE segment count ".concat(segmentPlanes.length, " exceeds DICOM maximum of 15 segments"));
357
+ }
358
+ const rowLength = columns && columns > 0 ? bitsAllocated === 1 ? columns % 8 === 0 ? columns / 8 : undefined : columns : undefined;
359
+ const encodedSegments = segmentPlanes.map(segment => {
360
+ const encoded = packBits(segment, rowLength);
361
+ if (encoded.length % 2 === 0) {
362
+ return encoded;
363
+ }
364
+ const padded = new Uint8Array(encoded.length + 1);
365
+ padded.set(encoded, 0);
366
+ return padded;
367
+ });
368
+ const header = new DataView(new ArrayBuffer(64));
369
+ header.setUint32(0, encodedSegments.length, true);
370
+ let offset = 64;
371
+ for (let i = 0; i < encodedSegments.length; i++) {
372
+ header.setUint32((i + 1) * 4, offset, true);
373
+ offset += encodedSegments[i].length;
374
+ }
375
+ const frameBytes = new Uint8Array(offset);
376
+ frameBytes.set(new Uint8Array(header.buffer), 0);
377
+ let writeOffset = 64;
378
+ for (let i = 0; i < encodedSegments.length; i++) {
379
+ frameBytes.set(encodedSegments[i], writeOffset);
380
+ writeOffset += encodedSegments[i].length;
381
+ }
382
+ return frameBytes.buffer;
383
+ }
384
+ function isUncompressedSegTransferSyntax(transferSyntaxUID) {
385
+ return transferSyntaxUID === EXPLICIT_VR_LITTLE_ENDIAN_TRANSFER_SYNTAX_UID;
386
+ }
387
+ function resolveFrameAtIndex(args, frameIndex) {
388
+ if (args.frames) {
389
+ return args.frames[frameIndex];
390
+ }
391
+ return args.buildFrame(frameIndex);
392
+ }
393
+ function materializeAllFrames(args) {
394
+ var _args$frames$length, _args$frames;
395
+ const frameCount = (_args$frames$length = (_args$frames = args.frames) === null || _args$frames === void 0 ? void 0 : _args$frames.length) !== null && _args$frames$length !== void 0 ? _args$frames$length : args.frameCount;
396
+ return Array.from({
397
+ length: frameCount
398
+ }, (_, frameIndex) => resolveFrameAtIndex(args, frameIndex));
399
+ }
400
+ function encodeCompressedFrameToTransferSyntax(frame, transferSyntaxUID, bitsAllocated, columns) {
401
+ if (transferSyntaxUID === RLE_LOSSLESS_TRANSFER_SYNTAX_UID) {
402
+ return encodeFrameToRle(frame, bitsAllocated, columns);
403
+ }
404
+ throw new Error("Unsupported compressed transfer syntax for SEG encoding: ".concat(transferSyntaxUID, ". ") + "Supported: ".concat(RLE_LOSSLESS_TRANSFER_SYNTAX_UID));
405
+ }
406
+ function encodeFramesToTransferSyntax(args) {
407
+ var _args$frames$length2, _args$frames2;
408
+ const transferSyntaxUID = args.transferSyntaxUID,
409
+ bitsAllocated = args.bitsAllocated,
410
+ columns = args.columns;
411
+ const frameCount = (_args$frames$length2 = (_args$frames2 = args.frames) === null || _args$frames2 === void 0 ? void 0 : _args$frames2.length) !== null && _args$frames$length2 !== void 0 ? _args$frames$length2 : args.frameCount;
412
+ if (isUncompressedSegTransferSyntax(transferSyntaxUID)) {
413
+ const frames = materializeAllFrames(args);
414
+ if (bitsAllocated === 1) {
415
+ const packedFrames = frames.map(frame => bitPackBinaryFrame(frame));
416
+ const combinedPacked = concatUint8Frames(packedFrames);
417
+ return {
418
+ transferSyntaxUID,
419
+ pixelDataVR: 'OW',
420
+ pixelData: combinedPacked
421
+ };
422
+ }
423
+ return {
424
+ transferSyntaxUID,
425
+ pixelDataVR: bitsAllocated <= 8 ? 'OB' : 'OW',
426
+ pixelData: bitsAllocated <= 8 ? concatUint8Frames(frames) : concatUint16Frames(frames)
427
+ };
428
+ }
429
+ const pixelData = [];
430
+ for (let frameIndex = 0; frameIndex < frameCount; frameIndex++) {
431
+ pixelData.push(encodeCompressedFrameToTransferSyntax(resolveFrameAtIndex(args, frameIndex), transferSyntaxUID, bitsAllocated, columns));
432
+ }
433
+ return {
434
+ transferSyntaxUID,
435
+ pixelDataVR: 'OB',
436
+ pixelData
437
+ };
438
+ }
439
+
440
+ export { EXPLICIT_VR_LITTLE_ENDIAN_TRANSFER_SYNTAX_UID, RLE_LOSSLESS_TRANSFER_SYNTAX_UID, bitPackBinaryFrame, createDecodeImageDataFromMultiframe, decodeSegFramesFromMultiframe, encodeFrameToRle, encodeFramesToTransferSyntax, getBitmapFramesFromDataset, getSegNumberOfFramesFromDataset, isUncompressedSegTransferSyntax, packBits, unpackBinaryFrameFromPacked };
@@ -1 +1 @@
1
- export declare const version = "5.4.10";
1
+ export declare const version = "5.4.12";
@@ -1,3 +1,3 @@
1
- const version = '5.4.10';
1
+ const version = '5.4.12';
2
2
 
3
3
  export { version };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cornerstonejs/adapters",
3
- "version": "5.4.10",
3
+ "version": "5.4.12",
4
4
  "description": "Adapters for Cornerstone3D to/from formats including DICOM SR and others",
5
5
  "module": "./dist/esm/index.js",
6
6
  "types": "./dist/esm/index.d.ts",
@@ -94,17 +94,17 @@
94
94
  "dependencies": {
95
95
  "@babel/runtime-corejs2": "7.26.10",
96
96
  "buffer": "6.0.3",
97
- "dcmjs": "0.50.1",
97
+ "dcmjs": "0.52.0",
98
98
  "gl-matrix": "3.4.3",
99
99
  "ndarray": "1.0.19"
100
100
  },
101
101
  "devDependencies": {
102
- "@cornerstonejs/core": "5.4.10",
103
- "@cornerstonejs/tools": "5.4.10"
102
+ "@cornerstonejs/core": "5.4.12",
103
+ "@cornerstonejs/tools": "5.4.12"
104
104
  },
105
105
  "peerDependencies": {
106
- "@cornerstonejs/core": "5.4.10",
107
- "@cornerstonejs/tools": "5.4.10"
106
+ "@cornerstonejs/core": "5.4.12",
107
+ "@cornerstonejs/tools": "5.4.12"
108
108
  },
109
- "gitHead": "523becb5856f2b6bb5f58c08eb2b5c66bd0b17e1"
109
+ "gitHead": "0b67d01ebc033cc338c3612c1237b5d94025cac2"
110
110
  }