@cornerstonejs/adapters 5.4.11 → 5.4.13

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.
@@ -1,5 +1,5 @@
1
1
  export function generateSegmentation(images: object[], inputLabelmaps3D: any | any[], userOptions?: any): Blob;
2
- export function fillSegmentation(segmentation: any, inputLabelmaps3D: any, userOptions?: {}): object;
2
+ export function fillSegmentation(segmentation: any, inputLabelmaps3D: any, userOptions?: {}, images?: any[], metadata?: any): object;
3
3
  export function _getLabelmapsFromReferencedFrameIndicies(labelmap3D: any, referencedFrameIndicies: any): any[];
4
4
  export function _createSegFromImages(images: any[], isMultiframe: boolean, options: any): any;
5
5
  export function generateToolState(referencedImageIds: string[], arrayBuffer: ArrayBuffer, metadataProvider: any, options: obj): [];
@@ -18,7 +18,7 @@ export function getSegmentMetadata(multiframe: any, seriesInstanceUid: any): {
18
18
  seriesInstanceUid: any;
19
19
  data: any[];
20
20
  };
21
- export function readFromUnpackedChunks(chunks: ArrayBuffer[], offset: number, length: number): Uint8Array;
21
+ export function readFromUnpackedChunks(chunks: Uint8Array[] | Uint16Array[], offset: number, length: number): Uint8Array | Uint16Array;
22
22
  export function getUnpackedOffsetAndLength(chunks: any, offset: any, length: any): {
23
23
  start: {
24
24
  chunkIndex: number;
@@ -4,6 +4,8 @@ import ndarray from 'ndarray';
4
4
  import getDatasetsFromImages from '../helpers/getDatasetsFromImages.js';
5
5
  import checkOrientation from '../helpers/checkOrientation.js';
6
6
  import { utilities as utilities$1 } from '@cornerstonejs/core';
7
+ import { getReferencedSourceImageSequenceItem, applyPerFrameFunctionalGroups } from '../Cornerstone3D/Segmentation/perFrameFunctionalGroups.js';
8
+ import { getBitmapFramesFromDataset, encodeFramesToTransferSyntax, RLE_LOSSLESS_TRANSFER_SYNTAX_UID as RLE_LOSSLESS_TRANSFER_SYNTAX_UID$1 } from '../Cornerstone3D/encodePixelData.js';
7
9
  import { Events } from '../enums/Events.js';
8
10
 
9
11
  const _utilities$orientatio = utilities.orientation,
@@ -19,6 +21,8 @@ const SegmentationDerivation = derivations.Segmentation;
19
21
  const _utilities$compressio = utilities.compression,
20
22
  encode = _utilities$compressio.encode,
21
23
  decode = _utilities$compressio.decode;
24
+ const RLE_LOSSLESS_TRANSFER_SYNTAX_UID = '1.2.840.10008.1.2.5';
25
+ const EXPLICIT_VR_LITTLE_ENDIAN_TRANSFER_SYNTAX_UID = '1.2.840.10008.1.2.1';
22
26
 
23
27
  /**
24
28
  *
@@ -29,7 +33,7 @@ const _utilities$compressio = utilities.compression,
29
33
  */
30
34
  const generateSegmentationDefaultOptions = {
31
35
  includeSliceSpacing: true,
32
- rleEncode: false
36
+ transferSyntaxUid: RLE_LOSSLESS_TRANSFER_SYNTAX_UID
33
37
  };
34
38
 
35
39
  /**
@@ -49,89 +53,200 @@ function generateSegmentation(images, inputLabelmaps3D) {
49
53
  return fillSegmentation(segmentation, inputLabelmaps3D, userOptions);
50
54
  }
51
55
 
56
+ /**
57
+ * The set of non-zero segment values actually present in a frame's pixel data,
58
+ * collected in a single pass. `segmentsOnLabelmap` can be stale, so presence is
59
+ * verified against the pixels — but once per frame, not with one full-frame
60
+ * scan per listed segment.
61
+ */
62
+ function segmentsPresentInFrame(pixelData) {
63
+ const presentSegments = new Set();
64
+ if (!pixelData) {
65
+ return presentSegments;
66
+ }
67
+ for (let i = 0; i < pixelData.length; i++) {
68
+ const value = pixelData[i];
69
+ if (value !== 0) {
70
+ presentSegments.add(value);
71
+ }
72
+ }
73
+ return presentSegments;
74
+ }
75
+
52
76
  /**
53
77
  * Fills a given segmentation object with data from the input labelmaps3D
54
78
  *
55
79
  * @param segmentation - The segmentation object to be filled.
56
80
  * @param inputLabelmaps3D - An array of 3D labelmaps, or a single 3D labelmap.
57
81
  * @param userOptions - Optional configuration settings. Will override the default options.
82
+ * - `transferSyntaxUid` — the output transfer syntax. Defaults to RLE Lossless
83
+ * (`1.2.840.10008.1.2.5`); Explicit VR Little Endian
84
+ * (`1.2.840.10008.1.2.1`) is also supported. Any other value throws.
85
+ * - `rleEncode` — **obsolete / ignored.** This option is no longer read. It
86
+ * never worked correctly in prior versions (the old path did not produce a
87
+ * valid RLE-encoded SEG), so it has been dropped rather than fixed. RLE
88
+ * output is now selected via `transferSyntaxUid` (RLE Lossless is the
89
+ * default), and encoding is handled by `encodeFramesToTransferSyntax`.
58
90
  *
59
91
  * @returns {object} The filled segmentation object.
60
92
  */
61
93
  function fillSegmentation(segmentation, inputLabelmaps3D) {
94
+ var _ref, _options$transferSynt;
62
95
  let userOptions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
96
+ let images = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : [];
97
+ let metadata = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null;
63
98
  const options = Object.assign({}, generateSegmentationDefaultOptions, userOptions);
64
99
 
65
100
  // Use another variable so we don't redefine labelmaps3D.
66
101
  const labelmaps3D = Array.isArray(inputLabelmaps3D) ? inputLabelmaps3D : [inputLabelmaps3D];
67
- let numberOfFrames = 0;
68
102
  const referencedFramesPerLabelmap = [];
103
+ const frameDescriptors = [];
69
104
  for (let labelmapIndex = 0; labelmapIndex < labelmaps3D.length; labelmapIndex++) {
70
105
  const labelmap3D = labelmaps3D[labelmapIndex];
71
106
  const labelmaps2D = labelmap3D.labelmaps2D,
72
- metadata = labelmap3D.metadata;
107
+ segmentMetadata = labelmap3D.metadata;
73
108
  const referencedFramesPerSegment = [];
74
- for (let i = 1; i < metadata.length; i++) {
75
- if (metadata[i]) {
109
+ for (let i = 1; i < segmentMetadata.length; i++) {
110
+ if (segmentMetadata[i]) {
76
111
  referencedFramesPerSegment[i] = [];
77
112
  }
78
113
  }
79
114
  for (let i = 0; i < labelmaps2D.length; i++) {
80
115
  const labelmap2D = labelmaps2D[i];
81
- if (labelmaps2D[i]) {
82
- const segmentsOnLabelmap = labelmap2D.segmentsOnLabelmap;
83
- segmentsOnLabelmap.forEach(segmentIndex => {
84
- if (segmentIndex !== 0) {
85
- referencedFramesPerSegment[segmentIndex].push(i);
86
- numberOfFrames++;
87
- }
88
- });
116
+ if (!(labelmap2D !== null && labelmap2D !== void 0 && labelmap2D.pixelData)) {
117
+ continue;
89
118
  }
119
+ const segmentsOnLabelmap = labelmap2D.segmentsOnLabelmap;
120
+ const presentSegments = segmentsPresentInFrame(labelmap2D.pixelData);
121
+ segmentsOnLabelmap.forEach(segmentIndex => {
122
+ if (segmentIndex !== 0 && segmentMetadata[segmentIndex] && referencedFramesPerSegment[segmentIndex] && presentSegments.has(segmentIndex)) {
123
+ referencedFramesPerSegment[segmentIndex].push(i);
124
+ }
125
+ });
90
126
  }
91
127
  referencedFramesPerLabelmap[labelmapIndex] = referencedFramesPerSegment;
92
128
  }
129
+ let numberOfFrames = 0;
130
+ for (let labelmapIndex = 0; labelmapIndex < labelmaps3D.length; labelmapIndex++) {
131
+ const referencedFramesPerSegment = referencedFramesPerLabelmap[labelmapIndex];
132
+ const labelmap3D = labelmaps3D[labelmapIndex];
133
+ const segmentMetadata = labelmap3D.metadata;
134
+ for (let segmentIndex = 1; segmentIndex < referencedFramesPerSegment.length; segmentIndex++) {
135
+ const referencedFrameIndicies = referencedFramesPerSegment[segmentIndex];
136
+ if (!(referencedFrameIndicies !== null && referencedFrameIndicies !== void 0 && referencedFrameIndicies.length) || !segmentMetadata[segmentIndex]) {
137
+ continue;
138
+ }
139
+ const labelmaps = _getLabelmapsFromReferencedFrameIndicies(labelmap3D, referencedFrameIndicies);
140
+ if (!labelmaps.length || !labelmaps.some(frame => (frame === null || frame === void 0 ? void 0 : frame.length) && frame.some(v => v !== 0))) {
141
+ continue;
142
+ }
143
+ numberOfFrames += referencedFrameIndicies.length;
144
+ }
145
+ }
146
+ if (numberOfFrames === 0) {
147
+ throw new Error('No non-empty segmentation frames found for SEG export');
148
+ }
93
149
  segmentation.setNumberOfFrames(numberOfFrames);
94
150
  for (let labelmapIndex = 0; labelmapIndex < labelmaps3D.length; labelmapIndex++) {
95
151
  const referencedFramesPerSegment = referencedFramesPerLabelmap[labelmapIndex];
96
152
  const labelmap3D = labelmaps3D[labelmapIndex];
97
- const metadata = labelmap3D.metadata;
153
+ const segmentMetadata = labelmap3D.metadata;
98
154
  for (let segmentIndex = 1; segmentIndex < referencedFramesPerSegment.length; segmentIndex++) {
99
155
  const referencedFrameIndicies = referencedFramesPerSegment[segmentIndex];
100
- if (referencedFrameIndicies) {
101
- // Frame numbers start from 1.
102
- const referencedFrameNumbers = referencedFrameIndicies.map(element => {
103
- return element + 1;
104
- });
105
- const segmentMetadata = metadata[segmentIndex];
106
- const labelmaps = _getLabelmapsFromReferencedFrameIndicies(labelmap3D, referencedFrameIndicies);
107
- segmentation.addSegmentFromLabelmap(segmentMetadata, labelmaps, segmentIndex, referencedFrameNumbers);
156
+ if (!(referencedFrameIndicies !== null && referencedFrameIndicies !== void 0 && referencedFrameIndicies.length) || !segmentMetadata[segmentIndex]) {
157
+ continue;
108
158
  }
159
+ const labelmaps = _getLabelmapsFromReferencedFrameIndicies(labelmap3D, referencedFrameIndicies);
160
+ if (!labelmaps.length || !labelmaps.some(frame => (frame === null || frame === void 0 ? void 0 : frame.length) && frame.some(v => v !== 0))) {
161
+ continue;
162
+ }
163
+
164
+ // Frame numbers start from 1.
165
+ const referencedFrameNumbers = referencedFrameIndicies.map(element => element + 1);
166
+ referencedFrameNumbers.forEach(frameNumber => {
167
+ frameDescriptors.push({
168
+ referencedSegmentNumber: segmentIndex,
169
+ sourceFrameIndex: frameNumber - 1
170
+ });
171
+ });
172
+ segmentation.addSegmentFromLabelmap(segmentMetadata[segmentIndex], labelmaps, segmentIndex, referencedFrameNumbers);
109
173
  }
110
174
  }
111
- if (options.rleEncode) {
112
- const rleEncodedFrames = encode(segmentation.dataset.PixelData, numberOfFrames, segmentation.dataset.Rows, segmentation.dataset.Columns);
113
-
114
- // Must use fractional now to RLE encode, as the DICOM standard only allows BitStored && BitsAllocated
115
- // to be 1 for BINARY. This is not ideal and there should be a better format for compression in this manner
116
- // added to the standard.
117
- segmentation.assignToDataset({
118
- BitsAllocated: '8',
119
- BitsStored: '8',
120
- HighBit: '7',
121
- SegmentationType: 'FRACTIONAL',
122
- SegmentationFractionalType: 'PROBABILITY',
123
- MaximumFractionalValue: '255'
175
+ if (frameDescriptors.length && images !== null && images !== void 0 && images.length && metadata) {
176
+ // Every SEG frame must reference a resolvable source SOP Instance UID.
177
+ // Reject rather than silently dropping frames: a dropped frame would make
178
+ // the per-frame functional groups disagree with the encoded PixelData and
179
+ // produce a SEG whose source-image references are unreliable.
180
+ const perFrameInputs = frameDescriptors.map(desc => {
181
+ const sourceImageSequenceItem = getReferencedSourceImageSequenceItem(images[desc.sourceFrameIndex], metadata);
182
+ if (!(sourceImageSequenceItem !== null && sourceImageSequenceItem !== void 0 && sourceImageSequenceItem.ReferencedSOPInstanceUID)) {
183
+ throw new Error("Cannot resolve a source ReferencedSOPInstanceUID for SEG frame " + "(sourceFrameIndex ".concat(desc.sourceFrameIndex, ", segment ") + "".concat(desc.referencedSegmentNumber, "). Refusing to write a SEG with ") + "unreliable source image references.");
184
+ }
185
+ return {
186
+ referencedSegmentNumber: desc.referencedSegmentNumber,
187
+ sourceImageSequenceItem
188
+ };
124
189
  });
125
- segmentation.dataset._meta.TransferSyntaxUID = {
126
- Value: ['1.2.840.10008.1.2.5'],
127
- vr: 'UI'
128
- };
129
- segmentation.dataset.SpecificCharacterSet = 'ISO_IR 192';
130
- segmentation.dataset._vrMap.PixelData = 'OB';
131
- segmentation.dataset.PixelData = rleEncodedFrames;
132
- } else {
133
- // If no rleEncoding, at least bitpack the data.
190
+ applyPerFrameFunctionalGroups(segmentation.dataset, perFrameInputs);
191
+ }
192
+ const transferSyntaxUid = (_ref = (_options$transferSynt = options.transferSyntaxUid) !== null && _options$transferSynt !== void 0 ? _options$transferSynt : options.transferSyntaxUID) !== null && _ref !== void 0 ? _ref : RLE_LOSSLESS_TRANSFER_SYNTAX_UID;
193
+ if (transferSyntaxUid === RLE_LOSSLESS_TRANSFER_SYNTAX_UID) {
194
+ const isBinaryBitmap = segmentation.dataset.SegmentationType === 'BINARY' && Number(segmentation.dataset.BitsAllocated) === 1;
195
+ if (isBinaryBitmap) {
196
+ segmentation.bitPackPixelData();
197
+ const _getBitmapFramesFromD = getBitmapFramesFromDataset(segmentation.dataset),
198
+ frames = _getBitmapFramesFromD.frames,
199
+ bitsAllocated = _getBitmapFramesFromD.bitsAllocated;
200
+ const _encodeFramesToTransf = encodeFramesToTransferSyntax({
201
+ transferSyntaxUID: RLE_LOSSLESS_TRANSFER_SYNTAX_UID$1,
202
+ frames,
203
+ bitsAllocated,
204
+ columns: Number(segmentation.dataset.Columns) || undefined
205
+ }),
206
+ pixelData = _encodeFramesToTransf.pixelData,
207
+ pixelDataVR = _encodeFramesToTransf.pixelDataVR;
208
+ segmentation.dataset.PixelData = pixelData;
209
+ segmentation.dataset._vrMap.PixelData = pixelDataVR;
210
+ if (!options.skipTransferSyntaxMeta) {
211
+ segmentation.dataset._meta.TransferSyntaxUID = {
212
+ Value: [RLE_LOSSLESS_TRANSFER_SYNTAX_UID],
213
+ vr: 'UI'
214
+ };
215
+ }
216
+ segmentation.dataset.SpecificCharacterSet = 'ISO_IR 192';
217
+ } else {
218
+ const rleEncodedFrames = encode(segmentation.dataset.PixelData, numberOfFrames, segmentation.dataset.Rows, segmentation.dataset.Columns);
219
+
220
+ // Fractional/8-bit labelmaps: legacy dcmjs row RLE (not valid for 1-bit packed binary).
221
+ segmentation.assignToDataset({
222
+ BitsAllocated: '8',
223
+ BitsStored: '8',
224
+ HighBit: '7',
225
+ SegmentationType: 'FRACTIONAL',
226
+ SegmentationFractionalType: 'PROBABILITY',
227
+ MaximumFractionalValue: '255'
228
+ });
229
+ if (!options.skipTransferSyntaxMeta) {
230
+ segmentation.dataset._meta.TransferSyntaxUID = {
231
+ Value: [RLE_LOSSLESS_TRANSFER_SYNTAX_UID],
232
+ vr: 'UI'
233
+ };
234
+ }
235
+ segmentation.dataset.SpecificCharacterSet = 'ISO_IR 192';
236
+ segmentation.dataset._vrMap.PixelData = 'OB';
237
+ segmentation.dataset.PixelData = rleEncodedFrames;
238
+ }
239
+ } else if (transferSyntaxUid === EXPLICIT_VR_LITTLE_ENDIAN_TRANSFER_SYNTAX_UID) {
240
+ // For explicit VR little endian, at least bitpack the data.
134
241
  segmentation.bitPackPixelData();
242
+ if (!options.skipTransferSyntaxMeta) {
243
+ segmentation.dataset._meta.TransferSyntaxUID = {
244
+ Value: [EXPLICIT_VR_LITTLE_ENDIAN_TRANSFER_SYNTAX_UID],
245
+ vr: 'UI'
246
+ };
247
+ }
248
+ } else {
249
+ throw new Error("Unsupported SEG transfer syntax: ".concat(transferSyntaxUid, ". ") + "Supported: ".concat(RLE_LOSSLESS_TRANSFER_SYNTAX_UID, ", ").concat(EXPLICIT_VR_LITTLE_ENDIAN_TRANSFER_SYNTAX_UID));
135
250
  }
136
251
  return segmentation;
137
252
  }
@@ -581,9 +696,9 @@ function checkSEGsOverlapping(pixelData, multiframe, imageIds, validOrientations
581
696
  frameSegmentsMapping.set(imageIdIndex, [frameSegment]);
582
697
  }
583
698
  }
584
- for (let _ref of frameSegmentsMapping.entries()) {
585
- var _ref2 = _slicedToArray(_ref, 2);
586
- let role = _ref2[1];
699
+ for (let _ref2 of frameSegmentsMapping.entries()) {
700
+ var _ref3 = _slicedToArray(_ref2, 2);
701
+ let role = _ref3[1];
587
702
  let temp2DArray = new TypedArrayConstructor(sliceLength).fill(0);
588
703
  for (let i = 0; i < role.length; ++i) {
589
704
  const frameSegment = role[i];
@@ -711,11 +826,29 @@ function insertOverlappingPixelDataPlanar(segmentsOnFrame, segmentsOnFrameArray,
711
826
  tempSegmentsOnFrame = structuredClone(segmentsOnFrameArray[m]);
712
827
  }
713
828
  }
829
+ function getReferencedSegmentNumberFromIdentificationSequence(segmentIdentificationSequence) {
830
+ if (!segmentIdentificationSequence) {
831
+ return undefined;
832
+ }
833
+ const normalized = Array.isArray(segmentIdentificationSequence) ? segmentIdentificationSequence[0] : segmentIdentificationSequence;
834
+ return normalized === null || normalized === void 0 ? void 0 : normalized.ReferencedSegmentNumber;
835
+ }
836
+ function getSharedFunctionalGroupsSequence(multiframe) {
837
+ const shared = multiframe === null || multiframe === void 0 ? void 0 : multiframe.SharedFunctionalGroupsSequence;
838
+ if (Array.isArray(shared)) {
839
+ return shared.length > 0 ? shared[0] : undefined;
840
+ }
841
+ return shared;
842
+ }
714
843
  const getSegmentIndex = (multiframe, frame) => {
715
- const PerFrameFunctionalGroupsSequence = multiframe.PerFrameFunctionalGroupsSequence,
716
- SharedFunctionalGroupsSequence = multiframe.SharedFunctionalGroupsSequence;
717
- const PerFrameFunctionalGroups = PerFrameFunctionalGroupsSequence[frame];
718
- return PerFrameFunctionalGroups && PerFrameFunctionalGroups.SegmentIdentificationSequence ? PerFrameFunctionalGroups.SegmentIdentificationSequence.ReferencedSegmentNumber : SharedFunctionalGroupsSequence.SegmentIdentificationSequence ? SharedFunctionalGroupsSequence.SegmentIdentificationSequence.ReferencedSegmentNumber : undefined;
844
+ const PerFrameFunctionalGroupsSequence = multiframe.PerFrameFunctionalGroupsSequence;
845
+ const PerFrameFunctionalGroups = PerFrameFunctionalGroupsSequence === null || PerFrameFunctionalGroupsSequence === void 0 ? void 0 : PerFrameFunctionalGroupsSequence[frame];
846
+ const fromPerFrame = getReferencedSegmentNumberFromIdentificationSequence(PerFrameFunctionalGroups === null || PerFrameFunctionalGroups === void 0 ? void 0 : PerFrameFunctionalGroups.SegmentIdentificationSequence);
847
+ if (fromPerFrame !== undefined) {
848
+ return fromPerFrame;
849
+ }
850
+ const shared = getSharedFunctionalGroupsSequence(multiframe);
851
+ return getReferencedSegmentNumberFromIdentificationSequence(shared === null || shared === void 0 ? void 0 : shared.SegmentIdentificationSequence);
719
852
  };
720
853
  function insertPixelDataPlanar(segmentsOnFrame, segmentsOnFrameArray, labelmapBufferArray, pixelData, multiframe, imageIds, validOrientations, metadataProvider, tolerance, TypedArrayConstructor, segmentsPixelIndices, sopUIDImageIdIndexMap, imageIdMaps, eventTarget, triggerEvent) {
721
854
  const SharedFunctionalGroupsSequence = multiframe.SharedFunctionalGroupsSequence,
@@ -894,13 +1027,14 @@ function getImageIdOfSourceImageBySourceImageSequence(SourceImageSequence, sopUI
894
1027
  } else if (baseImageId.includes('dicomfile:')) {
895
1028
  // dicomfile base 1, despite having frame=
896
1029
  return baseImageId.replace(/frame=\d+/, "frame=".concat(ReferencedFrameNumber));
897
- } else if (baseImageId.includes('frame=')) {
898
- return baseImageId.replace(/frame=\d+/, "frame=".concat(ReferencedFrameNumber - 1));
1030
+ } else if (baseImageId.includes('frame=') || baseImageId.includes('wadouri:')) {
1031
+ // OHIF local/wadouri use 1-based ?frame= / &frame= (same as dicomfile:).
1032
+ return baseImageId.replace(/frame=\d+/, "frame=".concat(ReferencedFrameNumber));
899
1033
  } else {
900
1034
  if (baseImageId.includes('wadors:')) {
901
1035
  return "".concat(baseImageId, "/frames/").concat(ReferencedFrameNumber);
902
1036
  } else {
903
- return "".concat(baseImageId, "?frame=").concat(ReferencedFrameNumber - 1);
1037
+ return "".concat(baseImageId, "?frame=").concat(ReferencedFrameNumber);
904
1038
  }
905
1039
  }
906
1040
  }
@@ -1049,28 +1183,40 @@ function getSegmentMetadata(multiframe, seriesInstanceUid) {
1049
1183
  }
1050
1184
 
1051
1185
  /**
1052
- * Reads a range of bytes from an array of ArrayBuffer chunks and
1053
- * aggregate them into a new Uint8Array.
1186
+ * Reads a range of SAMPLES (typed-array elements, not bytes) from an array of
1187
+ * typed-array chunks and aggregates them into a new typed array of the same
1188
+ * element type. Chunks may be Uint8Array (8-bit / packed binary) or
1189
+ * Uint16Array (16-bit labelmaps); offsets and lengths are in elements so the
1190
+ * same sample-indexed math works for both widths.
1054
1191
  *
1055
- * @param {ArrayBuffer[]} chunks - An array of ArrayBuffer chunks.
1056
- * @param {number} offset - The offset of the first byte to read.
1057
- * @param {number} length - The number of bytes to read.
1058
- * @returns {Uint8Array} A new Uint8Array containing the requested bytes.
1192
+ * @param {Uint8Array[]|Uint16Array[]} chunks - Typed-array chunks (all the same type).
1193
+ * @param {number} offset - The offset of the first sample to read.
1194
+ * @param {number} length - The number of samples to read.
1195
+ * @returns {Uint8Array|Uint16Array} A view/copy containing the requested samples.
1059
1196
  */
1060
1197
  function readFromUnpackedChunks(chunks, offset, length) {
1198
+ var _chunks$0$constructor, _chunks$, _TypedArray$BYTES_PER;
1061
1199
  const mapping = getUnpackedOffsetAndLength(chunks, offset, length);
1062
-
1200
+ const TypedArray = (_chunks$0$constructor = (_chunks$ = chunks[0]) === null || _chunks$ === void 0 ? void 0 : _chunks$.constructor) !== null && _chunks$0$constructor !== void 0 ? _chunks$0$constructor : Uint8Array;
1201
+ const bytesPerElement = (_TypedArray$BYTES_PER = TypedArray.BYTES_PER_ELEMENT) !== null && _TypedArray$BYTES_PER !== void 0 ? _TypedArray$BYTES_PER : 1;
1202
+
1203
+ // Chunks are typically subarray views that share one backing ArrayBuffer, so
1204
+ // `chunk.buffer` is the whole buffer (byte 0 = chunk 0) while the computed
1205
+ // offsets are chunk-relative. Add each chunk's own byteOffset so a view into
1206
+ // chunk N reads chunk N's bytes and not chunk 0's; element offsets are scaled
1207
+ // by the chunk's element width so 16-bit chunks are not read as bytes.
1063
1208
  // If all the data is in one chunk, we can just slice that chunk
1064
1209
  if (mapping.start.chunkIndex === mapping.end.chunkIndex) {
1065
- return new Uint8Array(chunks[mapping.start.chunkIndex].buffer, mapping.start.offset, length);
1210
+ const chunk = chunks[mapping.start.chunkIndex];
1211
+ return new TypedArray(chunk.buffer, chunk.byteOffset + mapping.start.offset * bytesPerElement, length);
1066
1212
  } else {
1067
- // If the data spans multiple chunks, we need to create a new Uint8Array and copy the data from each chunk
1068
- let result = new Uint8Array(length);
1213
+ // If the data spans multiple chunks, we need to create a new typed array and copy the data from each chunk
1214
+ let result = new TypedArray(length);
1069
1215
  let resultOffset = 0;
1070
1216
  for (let i = mapping.start.chunkIndex; i <= mapping.end.chunkIndex; i++) {
1071
1217
  let start = i === mapping.start.chunkIndex ? mapping.start.offset : 0;
1072
1218
  let end = i === mapping.end.chunkIndex ? mapping.end.offset : chunks[i].length;
1073
- result.set(new Uint8Array(chunks[i].buffer, start, end - start), resultOffset);
1219
+ result.set(new TypedArray(chunks[i].buffer, chunks[i].byteOffset + start * bytesPerElement, end - start), resultOffset);
1074
1220
  resultOffset += end - start;
1075
1221
  }
1076
1222
  return result;
@@ -1112,10 +1258,10 @@ function calculateCentroid(imageIdIndexBufferIndex, multiframe, metadataProvider
1112
1258
  let worldYAcc = 0;
1113
1259
  let worldZAcc = 0;
1114
1260
  let count = 0;
1115
- for (const _ref3 of Object.entries(imageIdIndexBufferIndex)) {
1116
- var _ref4 = _slicedToArray(_ref3, 2);
1117
- const imageIdIndex = _ref4[0];
1118
- const bufferIndices = _ref4[1];
1261
+ for (const _ref4 of Object.entries(imageIdIndexBufferIndex)) {
1262
+ var _ref5 = _slicedToArray(_ref4, 2);
1263
+ const imageIdIndex = _ref5[0];
1264
+ const bufferIndices = _ref5[1];
1119
1265
  const z = Number(imageIdIndex);
1120
1266
  if (!bufferIndices || bufferIndices.length === 0) {
1121
1267
  continue;
@@ -4,5 +4,14 @@ interface IOptions {
4
4
  type Options = IOptions & {
5
5
  [key: string]: number | boolean | unknown | string;
6
6
  };
7
+ declare function toLabelmap3DArray(inputLabelmaps3D: any): any[];
8
+ declare function collectNonEmptyFrameIndices(labelmap3DArray: any): number[];
9
+ declare function resolveReferencedImagesForExport(images: Array<{
10
+ imageId?: string;
11
+ } | undefined | null>, frameIndices: number[]): {
12
+ imageId?: string;
13
+ }[];
14
+ declare function maxSegmentValue(labelmap3DArray: any, frameIndices: number[]): number;
15
+ declare function collectSegmentSequence(labelmap3DArray: any): Record<string, unknown>[];
7
16
  declare function generateSegmentation(images: any, labelmaps: any, metadata: any, options?: Options): any;
8
- export { generateSegmentation };
17
+ export { generateSegmentation, toLabelmap3DArray, collectNonEmptyFrameIndices, resolveReferencedImagesForExport, maxSegmentValue, collectSegmentSequence, };