@cosyte/dicom 0.0.19 → 0.1.0
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/CHANGELOG.md +761 -0
- package/README.md +329 -153
- package/dist/index.cjs +2758 -850
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1658 -269
- package/dist/index.d.ts +1658 -269
- package/dist/index.mjs +2755 -852
- package/dist/index.mjs.map +1 -1
- package/package.json +66 -37
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Buffer } from 'buffer';
|
|
2
|
-
import {
|
|
2
|
+
import { inflateRawSync, deflateRawSync } from 'zlib';
|
|
3
3
|
import { createHash } from 'crypto';
|
|
4
4
|
|
|
5
5
|
var __defProp = Object.defineProperty;
|
|
@@ -9,7 +9,7 @@ var __export = (target, all) => {
|
|
|
9
9
|
};
|
|
10
10
|
|
|
11
11
|
// src/version.ts
|
|
12
|
-
var VERSION = "0.0
|
|
12
|
+
var VERSION = "0.1.0";
|
|
13
13
|
|
|
14
14
|
// src/dictionary/index.ts
|
|
15
15
|
var dictionary_exports = {};
|
|
@@ -1259,6 +1259,7 @@ var KEYWORDS = {
|
|
|
1259
1259
|
"DopplerSampleVolumeYPosition": "0018603B",
|
|
1260
1260
|
"DopplerSampleVolumeYPositionRetired": "0018603A",
|
|
1261
1261
|
"DoseCalculationAlgorithmSequence": "30040081",
|
|
1262
|
+
"DoseCalculationModelName": "3004007F",
|
|
1262
1263
|
"DoseCalculationModelParameterSequence": "30040083",
|
|
1263
1264
|
"DoseCalculationModelSequence": "30040080",
|
|
1264
1265
|
"DoseCalibrationConditionsSequence": "300C0120",
|
|
@@ -9346,6 +9347,7 @@ var TAGS = {
|
|
|
9346
9347
|
"30040070": { tag: "30040070", keyword: "DVHMinimumDose", name: "DVH Minimum Dose", vr: ["DS"], vm: "1", retired: false },
|
|
9347
9348
|
"30040072": { tag: "30040072", keyword: "DVHMaximumDose", name: "DVH Maximum Dose", vr: ["DS"], vm: "1", retired: false },
|
|
9348
9349
|
"30040074": { tag: "30040074", keyword: "DVHMeanDose", name: "DVH Mean Dose", vr: ["DS"], vm: "1", retired: false },
|
|
9350
|
+
"3004007F": { tag: "3004007F", keyword: "DoseCalculationModelName", name: "Dose Calculation Model Name", vr: ["LO"], vm: "1", retired: false },
|
|
9349
9351
|
"30040080": { tag: "30040080", keyword: "DoseCalculationModelSequence", name: "Dose Calculation Model Sequence", vr: ["SQ"], vm: "1", retired: false },
|
|
9350
9352
|
"30040081": { tag: "30040081", keyword: "DoseCalculationAlgorithmSequence", name: "Dose Calculation Algorithm Sequence", vr: ["SQ"], vm: "1", retired: false },
|
|
9351
9353
|
"30040082": { tag: "30040082", keyword: "CommissioningStatus", name: "Commissioning Status", vr: ["CS"], vm: "1", retired: false },
|
|
@@ -11090,6 +11092,129 @@ function uid(uidValue) {
|
|
|
11090
11092
|
return FROZEN_UIDS[uidValue];
|
|
11091
11093
|
}
|
|
11092
11094
|
|
|
11095
|
+
// src/dataset/directory.ts
|
|
11096
|
+
var MEDIA_STORAGE_DIRECTORY_STORAGE_UID = "1.2.840.10008.1.3.10";
|
|
11097
|
+
var TS_DEFLATED_LE = "1.2.840.10008.1.2.1.99";
|
|
11098
|
+
var DIRECTORY_TAGS = {
|
|
11099
|
+
/** Offset of the First Directory Record of the Root Directory Entity. */
|
|
11100
|
+
FIRST_ROOT_RECORD: "00041200",
|
|
11101
|
+
/** Offset of the Last Directory Record of the Root Directory Entity. */
|
|
11102
|
+
LAST_ROOT_RECORD: "00041202",
|
|
11103
|
+
/** Directory Record Sequence. */
|
|
11104
|
+
RECORD_SEQUENCE: "00041220",
|
|
11105
|
+
/** Offset of the Next Directory Record. */
|
|
11106
|
+
NEXT_RECORD: "00041400",
|
|
11107
|
+
/** Offset of Referenced Lower-Level Directory Entity. */
|
|
11108
|
+
LOWER_LEVEL: "00041420",
|
|
11109
|
+
/** Directory Record Type. */
|
|
11110
|
+
RECORD_TYPE: "00041430",
|
|
11111
|
+
/** Referenced File ID. */
|
|
11112
|
+
REFERENCED_FILE_ID: "00041500"
|
|
11113
|
+
};
|
|
11114
|
+
var ZERO = Object.freeze({ kind: "zero" });
|
|
11115
|
+
var MALFORMED = Object.freeze({ kind: "malformed" });
|
|
11116
|
+
function readOffsetValue(el) {
|
|
11117
|
+
if (el.vr === "SQ" || el.length !== 4 || el.rawBytes.length !== 4) return MALFORMED;
|
|
11118
|
+
const value = el.littleEndian ? el.rawBytes.readUInt32LE(0) : el.rawBytes.readUInt32BE(0);
|
|
11119
|
+
return value === 0 ? ZERO : { kind: "offset", value };
|
|
11120
|
+
}
|
|
11121
|
+
function isDicomdir(fileMeta) {
|
|
11122
|
+
return fileMeta?.mediaStorageSOPClassUID === MEDIA_STORAGE_DIRECTORY_STORAGE_UID;
|
|
11123
|
+
}
|
|
11124
|
+
function isDeflated(fileMeta) {
|
|
11125
|
+
return fileMeta?.transferSyntaxUID === TS_DEFLATED_LE;
|
|
11126
|
+
}
|
|
11127
|
+
function directoryRecords(source) {
|
|
11128
|
+
const items = source.get(DIRECTORY_TAGS.RECORD_SEQUENCE)?.items ?? [];
|
|
11129
|
+
const byFileOffset = /* @__PURE__ */ new Map();
|
|
11130
|
+
const shared = /* @__PURE__ */ new Set();
|
|
11131
|
+
items.forEach((item, index) => {
|
|
11132
|
+
const at3 = item.fileOffset;
|
|
11133
|
+
if (at3 === void 0) return;
|
|
11134
|
+
if (byFileOffset.has(at3)) shared.add(at3);
|
|
11135
|
+
else byFileOffset.set(at3, index);
|
|
11136
|
+
});
|
|
11137
|
+
for (const at3 of shared) byFileOffset.delete(at3);
|
|
11138
|
+
return { items, byFileOffset };
|
|
11139
|
+
}
|
|
11140
|
+
function csValues(el) {
|
|
11141
|
+
if (el === void 0) return void 0;
|
|
11142
|
+
const text = el.rawBytes.toString("latin1").replace(/[\0 ]+$/u, "");
|
|
11143
|
+
return Object.freeze(text === "" ? [] : text.split("\\").map((v) => v.replace(/^ +| +$/gu, "")));
|
|
11144
|
+
}
|
|
11145
|
+
function analyzeDirectory(source) {
|
|
11146
|
+
if (!isDicomdir(source.fileMeta)) return void 0;
|
|
11147
|
+
const deflated = isDeflated(source.fileMeta);
|
|
11148
|
+
const { items, byFileOffset } = directoryRecords(source);
|
|
11149
|
+
const findings = [];
|
|
11150
|
+
let deflatedOffset;
|
|
11151
|
+
const resolve = (element, item) => {
|
|
11152
|
+
if (element === void 0) return void 0;
|
|
11153
|
+
const offset = readOffsetValue(element);
|
|
11154
|
+
if (offset.kind === "zero") return void 0;
|
|
11155
|
+
if (offset.kind === "malformed") {
|
|
11156
|
+
findings.push({ kind: "malformed", element, item });
|
|
11157
|
+
return void 0;
|
|
11158
|
+
}
|
|
11159
|
+
if (deflated) {
|
|
11160
|
+
deflatedOffset ??= { kind: "deflated", element, item };
|
|
11161
|
+
return void 0;
|
|
11162
|
+
}
|
|
11163
|
+
const target = byFileOffset.get(offset.value);
|
|
11164
|
+
if (target === void 0) findings.push({ kind: "unresolved", element, item });
|
|
11165
|
+
return { element, item, target };
|
|
11166
|
+
};
|
|
11167
|
+
const first = resolve(source.get(DIRECTORY_TAGS.FIRST_ROOT_RECORD), void 0);
|
|
11168
|
+
resolve(source.get(DIRECTORY_TAGS.LAST_ROOT_RECORD), void 0);
|
|
11169
|
+
const next = [];
|
|
11170
|
+
const lower = [];
|
|
11171
|
+
for (const item of items) {
|
|
11172
|
+
next.push(resolve(item.get(DIRECTORY_TAGS.NEXT_RECORD), item));
|
|
11173
|
+
lower.push(resolve(item.get(DIRECTORY_TAGS.LOWER_LEVEL), item));
|
|
11174
|
+
}
|
|
11175
|
+
if (deflatedOffset !== void 0) findings.push(deflatedOffset);
|
|
11176
|
+
const children = [];
|
|
11177
|
+
const records = items.map((item, index) => {
|
|
11178
|
+
const lowerLevel = [];
|
|
11179
|
+
children.push(lowerLevel);
|
|
11180
|
+
return Object.freeze({
|
|
11181
|
+
index,
|
|
11182
|
+
type: csValues(item.get(DIRECTORY_TAGS.RECORD_TYPE))?.[0],
|
|
11183
|
+
referencedFileId: csValues(item.get(DIRECTORY_TAGS.REFERENCED_FILE_ID)),
|
|
11184
|
+
lowerLevel,
|
|
11185
|
+
item
|
|
11186
|
+
});
|
|
11187
|
+
});
|
|
11188
|
+
const reached = /* @__PURE__ */ new Set();
|
|
11189
|
+
const expand = [];
|
|
11190
|
+
const chain = (start, into) => {
|
|
11191
|
+
const entity = [];
|
|
11192
|
+
let link = start;
|
|
11193
|
+
while (link?.target !== void 0) {
|
|
11194
|
+
const at3 = link.target;
|
|
11195
|
+
if (reached.has(at3)) {
|
|
11196
|
+
findings.push({ kind: "revisited", element: link.element, item: link.item });
|
|
11197
|
+
break;
|
|
11198
|
+
}
|
|
11199
|
+
reached.add(at3);
|
|
11200
|
+
into.push(records[at3]);
|
|
11201
|
+
entity.push(at3);
|
|
11202
|
+
link = next[at3];
|
|
11203
|
+
}
|
|
11204
|
+
for (const at3 of entity.reverse()) expand.push(at3);
|
|
11205
|
+
};
|
|
11206
|
+
const root = [];
|
|
11207
|
+
chain(first, root);
|
|
11208
|
+
for (let at3 = expand.pop(); at3 !== void 0; at3 = expand.pop()) {
|
|
11209
|
+
chain(lower[at3], children[at3]);
|
|
11210
|
+
}
|
|
11211
|
+
for (const list of children) Object.freeze(list);
|
|
11212
|
+
return {
|
|
11213
|
+
directory: Object.freeze({ records: Object.freeze(records), root: Object.freeze(root) }),
|
|
11214
|
+
findings
|
|
11215
|
+
};
|
|
11216
|
+
}
|
|
11217
|
+
|
|
11093
11218
|
// src/dataset/helpers/read.ts
|
|
11094
11219
|
function readString(ds, tag) {
|
|
11095
11220
|
const v = ds.get(tag)?.value;
|
|
@@ -11515,21 +11640,23 @@ var Dataset = class {
|
|
|
11515
11640
|
fileMeta;
|
|
11516
11641
|
warnings;
|
|
11517
11642
|
/**
|
|
11518
|
-
* Element map, keyed by uppercase 8-hex tag.
|
|
11519
|
-
*
|
|
11520
|
-
*
|
|
11643
|
+
* Element map, keyed by uppercase 8-hex tag. Reached publicly through the
|
|
11644
|
+
* navigation surface; kept `protected` here so only subclasses (`Item`, and
|
|
11645
|
+
* any later extension) can introspect it directly.
|
|
11521
11646
|
*
|
|
11522
11647
|
* @internal
|
|
11523
11648
|
*/
|
|
11524
11649
|
_elements;
|
|
11525
|
-
/** Memoised
|
|
11650
|
+
/** Memoised domain views (built once, on first access). */
|
|
11526
11651
|
_patient;
|
|
11527
11652
|
_study;
|
|
11528
11653
|
_series;
|
|
11529
11654
|
_image;
|
|
11655
|
+
/** Boxed so a memoised "not a DICOMDIR" is told apart from "not read yet". */
|
|
11656
|
+
_directory;
|
|
11530
11657
|
/**
|
|
11531
|
-
* Construct a new structural `Dataset`.
|
|
11532
|
-
*
|
|
11658
|
+
* Construct a new structural `Dataset`. The warnings array is frozen at
|
|
11659
|
+
* the model boundary.
|
|
11533
11660
|
*
|
|
11534
11661
|
* @internal
|
|
11535
11662
|
*/
|
|
@@ -11598,7 +11725,7 @@ var Dataset = class {
|
|
|
11598
11725
|
return el !== void 0 ? [el] : [];
|
|
11599
11726
|
}
|
|
11600
11727
|
/**
|
|
11601
|
-
* Patient-identity view
|
|
11728
|
+
* Patient-identity view. Fail-safe typed-absent fields; `id` is
|
|
11602
11729
|
* **not** globally unique - match on the `{id, issuerOfId, ...}` tuple
|
|
11603
11730
|
* plus `otherIds`, never on a bare `(0010,0020)`. Memoised on first read.
|
|
11604
11731
|
*
|
|
@@ -11613,7 +11740,7 @@ var Dataset = class {
|
|
|
11613
11740
|
return this._patient ??= buildPatient(this);
|
|
11614
11741
|
}
|
|
11615
11742
|
/**
|
|
11616
|
-
* Study-identity view
|
|
11743
|
+
* Study-identity view. `instanceUid` is the cross-system study
|
|
11617
11744
|
* key; `accessionNumber` ties it to the order. Memoised on first read.
|
|
11618
11745
|
*
|
|
11619
11746
|
* @example
|
|
@@ -11627,7 +11754,7 @@ var Dataset = class {
|
|
|
11627
11754
|
return this._study ??= buildStudy(this);
|
|
11628
11755
|
}
|
|
11629
11756
|
/**
|
|
11630
|
-
* Series-identity & co-registration view
|
|
11757
|
+
* Series-identity & co-registration view. A shared
|
|
11631
11758
|
* `frameOfReferenceUid` means images are spatially co-registered.
|
|
11632
11759
|
* Memoised on first read.
|
|
11633
11760
|
*
|
|
@@ -11642,7 +11769,7 @@ var Dataset = class {
|
|
|
11642
11769
|
return this._series ??= buildSeries(this);
|
|
11643
11770
|
}
|
|
11644
11771
|
/**
|
|
11645
|
-
* Pixel-interpretation + geometry view
|
|
11772
|
+
* Pixel-interpretation + geometry view. Surfaces exactly
|
|
11646
11773
|
* what a renderer needs without guessing: `rescaleSlope`/`signed`/
|
|
11647
11774
|
* `photometricInterpretation` stay absent rather than defaulted, and the
|
|
11648
11775
|
* three pixel-spacing tags are distinct. Memoised on first read.
|
|
@@ -11657,110 +11784,42 @@ var Dataset = class {
|
|
|
11657
11784
|
get image() {
|
|
11658
11785
|
return this._image ??= buildImage(this);
|
|
11659
11786
|
}
|
|
11660
|
-
};
|
|
11661
|
-
|
|
11662
|
-
// src/parser/errors.ts
|
|
11663
|
-
var FATAL_CODES = {
|
|
11664
|
-
NOT_DICOM_PART_10: "NOT_DICOM_PART_10",
|
|
11665
|
-
INVALID_FILE_META: "INVALID_FILE_META",
|
|
11666
|
-
UNSUPPORTED_TRANSFER_SYNTAX: "UNSUPPORTED_TRANSFER_SYNTAX",
|
|
11667
|
-
EMPTY_INPUT: "EMPTY_INPUT"
|
|
11668
|
-
};
|
|
11669
|
-
var OFFSET_FRAMES = {
|
|
11670
|
-
/**
|
|
11671
|
-
* Byte 0 is byte 0 of the buffer handed to `parseDicom`. The only frame in
|
|
11672
|
-
* which indexing the caller's own input by `byteOffset` is meaningful.
|
|
11673
|
-
*/
|
|
11674
|
-
INPUT: "input",
|
|
11675
|
-
/**
|
|
11676
|
-
* Byte 0 is byte 0 of the inflated Data Set of a Deflated Explicit VR LE
|
|
11677
|
-
* object (`1.2.840.10008.1.2.1.99`). The compressed input holds no such
|
|
11678
|
-
* byte, so the offset does not index it at any scale.
|
|
11679
|
-
*/
|
|
11680
|
-
INFLATED_DATASET: "inflated-dataset",
|
|
11681
|
-
/**
|
|
11682
|
-
* Byte 0 is byte 0 of a slice this parser cut from inside a Value Field: a
|
|
11683
|
-
* defined-length Sequence Item's value, or an `SQ`/`UN` value handed to a
|
|
11684
|
-
* descent. **Where that slice begins is deliberately not published** - see
|
|
11685
|
-
* this table's own note.
|
|
11686
|
-
*/
|
|
11687
|
-
VALUE_SLICE: "value-slice"
|
|
11688
|
-
};
|
|
11689
|
-
var DicomParseError = class extends Error {
|
|
11690
|
-
code;
|
|
11691
|
-
byteOffset;
|
|
11692
|
-
/**
|
|
11693
|
-
* The coordinate system {@link DicomParseError.byteOffset} is counted in.
|
|
11694
|
-
* See {@link OFFSET_FRAMES}.
|
|
11695
|
-
*/
|
|
11696
|
-
offsetFrame;
|
|
11697
|
-
snippet;
|
|
11698
|
-
contextPath;
|
|
11699
11787
|
/**
|
|
11700
|
-
*
|
|
11701
|
-
*
|
|
11702
|
-
* `
|
|
11703
|
-
*
|
|
11704
|
-
*
|
|
11788
|
+
* The DICOMDIR Directory Record tree, or `undefined` when this Dataset is not
|
|
11789
|
+
* a DICOMDIR (its File Meta Media Storage SOP Class UID is not
|
|
11790
|
+
* `1.2.840.10008.1.3.10`). Read from the four offset attributes (PS3.3 2026d
|
|
11791
|
+
* Table F.3-3): `root` is the record `(0004,1200)` names and each
|
|
11792
|
+
* `(0004,1400)` successor, and each record's `lowerLevel` is the record its
|
|
11793
|
+
* `(0004,1420)` names and each successor. An offset resolves only when it is
|
|
11794
|
+
* exactly the file offset of an Item of the Directory Record Sequence
|
|
11795
|
+
* `(0004,1220)`; one that is not names no record, and `parseDicom` warns
|
|
11796
|
+
* (`DICOM_DIRECTORY_OFFSET_UNRESOLVED`, `DICOM_DIRECTORY_OFFSET_MALFORMED`,
|
|
11797
|
+
* `DICOM_DIRECTORY_RECORD_REVISITED`, `DICOM_DIRECTORY_OFFSET_DEFLATED`).
|
|
11798
|
+
* Memoised on first read.
|
|
11705
11799
|
*
|
|
11706
|
-
*
|
|
11800
|
+
* Limits: record keys are not checked against PS3.3 F.5, the File-set
|
|
11801
|
+
* Consistency Flag and `(0004,1202)`'s agreement with the end of the root
|
|
11802
|
+
* chain are not checked, and under Deflated Explicit VR LE no offset resolves,
|
|
11803
|
+
* so every record is listed in `records` and none is linked.
|
|
11804
|
+
*
|
|
11805
|
+
* @example
|
|
11806
|
+
* ```ts
|
|
11807
|
+
* import { parseDicom } from "@cosyte/dicom";
|
|
11808
|
+
* const dir = parseDicom(buf).directory;
|
|
11809
|
+
* for (const patient of dir?.root ?? []) {
|
|
11810
|
+
* for (const study of patient.lowerLevel) {
|
|
11811
|
+
* for (const series of study.lowerLevel) {
|
|
11812
|
+
* for (const image of series.lowerLevel) console.log(image.referencedFileId);
|
|
11813
|
+
* }
|
|
11814
|
+
* }
|
|
11815
|
+
* }
|
|
11816
|
+
* ```
|
|
11707
11817
|
*/
|
|
11708
|
-
|
|
11709
|
-
|
|
11710
|
-
|
|
11711
|
-
this.name = "DicomParseError";
|
|
11712
|
-
this.code = code;
|
|
11713
|
-
this.byteOffset = byteOffset;
|
|
11714
|
-
this.offsetFrame = offsetFrame;
|
|
11715
|
-
this.snippet = snippet;
|
|
11716
|
-
this.contextPath = contextPath;
|
|
11818
|
+
get directory() {
|
|
11819
|
+
this._directory ??= { value: analyzeDirectory(this)?.directory };
|
|
11820
|
+
return this._directory.value;
|
|
11717
11821
|
}
|
|
11718
11822
|
};
|
|
11719
|
-
function buildSnippet(buffer, offset) {
|
|
11720
|
-
if (offset < 0 || offset >= buffer.length) return "";
|
|
11721
|
-
const end = Math.min(offset + 16, buffer.length);
|
|
11722
|
-
const slice = buffer.subarray(offset, end);
|
|
11723
|
-
const parts = [];
|
|
11724
|
-
for (const b of slice) {
|
|
11725
|
-
parts.push(b.toString(16).padStart(2, "0"));
|
|
11726
|
-
}
|
|
11727
|
-
return parts.join(" ");
|
|
11728
|
-
}
|
|
11729
|
-
|
|
11730
|
-
// src/parser/emit.ts
|
|
11731
|
-
function makeEmitter(ctx) {
|
|
11732
|
-
const escalate = (w) => {
|
|
11733
|
-
throw new DicomParseError(
|
|
11734
|
-
// D-35 cast: the WarningCode union does not overlap FatalCode at the
|
|
11735
|
-
// type level, but at runtime the strict-thrown error carries the
|
|
11736
|
-
// warning code so consumers can narrow on err.code uniformly.
|
|
11737
|
-
w.code,
|
|
11738
|
-
w.message,
|
|
11739
|
-
w.position.byteOffset,
|
|
11740
|
-
// Both come off the SAME frame object, so an escalation cannot name one
|
|
11741
|
-
// frame and cut its bytes from another. `DicomParseWarning.position`
|
|
11742
|
-
// itself carries no frame - that is `PRE-EXISTING` and stated on
|
|
11743
|
-
// `DicomPosition`, not closed here.
|
|
11744
|
-
ctx.frame.name,
|
|
11745
|
-
buildSnippet(ctx.frame.buffer, w.position.byteOffset),
|
|
11746
|
-
w.position.contextPath
|
|
11747
|
-
);
|
|
11748
|
-
};
|
|
11749
|
-
return (w) => {
|
|
11750
|
-
if (ctx.strict) escalate(w);
|
|
11751
|
-
if (ctx.profile !== void 0) {
|
|
11752
|
-
if (ctx.profile.suppressions.has(w.code)) return;
|
|
11753
|
-
if (ctx.profile.escalations.has(w.code)) escalate(w);
|
|
11754
|
-
}
|
|
11755
|
-
ctx.warnings.push(w);
|
|
11756
|
-
if (ctx.onWarning !== void 0) {
|
|
11757
|
-
try {
|
|
11758
|
-
ctx.onWarning(w);
|
|
11759
|
-
} catch {
|
|
11760
|
-
}
|
|
11761
|
-
}
|
|
11762
|
-
};
|
|
11763
|
-
}
|
|
11764
11823
|
|
|
11765
11824
|
// src/parser/endian.ts
|
|
11766
11825
|
var BE_VR_STRIDE = Object.freeze({
|
|
@@ -11781,7 +11840,7 @@ var BE_VR_STRIDE = Object.freeze({
|
|
|
11781
11840
|
OV: 8,
|
|
11782
11841
|
SV: 8,
|
|
11783
11842
|
UV: 8,
|
|
11784
|
-
// No swap - byte streams
|
|
11843
|
+
// No swap - byte streams and ASCII / spec-defined VRs.
|
|
11785
11844
|
OB: 0,
|
|
11786
11845
|
UN: 0,
|
|
11787
11846
|
AE: 0,
|
|
@@ -11825,377 +11884,13 @@ function renderTag(tag) {
|
|
|
11825
11884
|
return lookup(tag) === void 0 ? WITHHELD : tag;
|
|
11826
11885
|
}
|
|
11827
11886
|
|
|
11828
|
-
// src/parser/fatals.ts
|
|
11829
|
-
var SUPPORTED_TRANSFER_SYNTAXES = "1.2.840.10008.1.2, 1.2.840.10008.1.2.1, 1.2.840.10008.1.2.2, 1.2.840.10008.1.2.1.99";
|
|
11830
|
-
var ZLIB_CODES = Object.freeze(
|
|
11831
|
-
/* @__PURE__ */ new Set([
|
|
11832
|
-
"Z_OK",
|
|
11833
|
-
"Z_STREAM_END",
|
|
11834
|
-
"Z_NEED_DICT",
|
|
11835
|
-
"Z_ERRNO",
|
|
11836
|
-
"Z_STREAM_ERROR",
|
|
11837
|
-
"Z_DATA_ERROR",
|
|
11838
|
-
"Z_MEM_ERROR",
|
|
11839
|
-
"Z_BUF_ERROR",
|
|
11840
|
-
"Z_VERSION_ERROR"
|
|
11841
|
-
])
|
|
11842
|
-
);
|
|
11843
|
-
var FATAL_MESSAGES = Object.freeze({
|
|
11844
|
-
EMPTY_INPUT: {
|
|
11845
|
-
code: FATAL_CODES.EMPTY_INPUT,
|
|
11846
|
-
message: "Input is empty."
|
|
11847
|
-
},
|
|
11848
|
-
EMPTY_INPUT_AFTER_NORMALIZATION: {
|
|
11849
|
-
code: FATAL_CODES.EMPTY_INPUT,
|
|
11850
|
-
message: "Input is empty after normalization."
|
|
11851
|
-
},
|
|
11852
|
-
NOT_DICOM_PART_10_REQUIRED: {
|
|
11853
|
-
code: FATAL_CODES.NOT_DICOM_PART_10,
|
|
11854
|
-
message: "Missing DICM magic at offset 128 (stripPreamble='require')."
|
|
11855
|
-
},
|
|
11856
|
-
NOT_DICOM_PART_10: {
|
|
11857
|
-
code: FATAL_CODES.NOT_DICOM_PART_10,
|
|
11858
|
-
message: "Input is not a DICOM Part 10 file (no DICM magic at offset 128 and no recognizable File Meta group at offset 0)."
|
|
11859
|
-
},
|
|
11860
|
-
// `{ts}` is NOT the UID. It is the PS3.6 registry's own name for the UID, or a
|
|
11861
|
-
// fixed phrase when PS3.6 does not publish one - see `renderTransferSyntax`.
|
|
11862
|
-
UNSUPPORTED_TRANSFER_SYNTAX: {
|
|
11863
|
-
code: FATAL_CODES.UNSUPPORTED_TRANSFER_SYNTAX,
|
|
11864
|
-
message: `{ts} in (0002,0010) is not supported by @cosyte/dicom v1 (supported: ${SUPPORTED_TRANSFER_SYNTAXES}).`
|
|
11865
|
-
},
|
|
11866
|
-
FILE_META_TRUNCATED: {
|
|
11867
|
-
code: FATAL_CODES.INVALID_FILE_META,
|
|
11868
|
-
message: "File Meta is truncated."
|
|
11869
|
-
},
|
|
11870
|
-
// The declared group length is deliberately absent. It is four bytes of the
|
|
11871
|
-
// document read as a 32-bit integer. **NOT because this code fires only when
|
|
11872
|
-
// those four bytes are fabricated** - an honestly truncated file raises it
|
|
11873
|
-
// with a perfectly correct group length, measured - but because they are four
|
|
11874
|
-
// bytes a sender wrote in either reading, and in the other one they are part
|
|
11875
|
-
// of somebody's value.
|
|
11876
|
-
FILE_META_GROUP_LENGTH_OVERRUNS: {
|
|
11877
|
-
code: FATAL_CODES.INVALID_FILE_META,
|
|
11878
|
-
message: "(0002,0000) FileMetaInformationGroupLength declares more bytes than remain in the input. The declared length and the count of bytes that remain are withheld; the byte offset locates the group."
|
|
11879
|
-
},
|
|
11880
|
-
FILE_META_TRANSFER_SYNTAX_MISSING: {
|
|
11881
|
-
code: FATAL_CODES.INVALID_FILE_META,
|
|
11882
|
-
message: "Required File Meta element (0002,0010) Transfer Syntax UID is missing or not UI."
|
|
11883
|
-
},
|
|
11884
|
-
TRUNCATED_DATASET_HEADER: {
|
|
11885
|
-
code: FATAL_CODES.INVALID_FILE_META,
|
|
11886
|
-
message: "Truncated dataset (header read past buffer end)."
|
|
11887
|
-
},
|
|
11888
|
-
TRUNCATED_FFFE_HEADER: {
|
|
11889
|
-
code: FATAL_CODES.INVALID_FILE_META,
|
|
11890
|
-
message: "Truncated dataset (FFFE header read past buffer end)."
|
|
11891
|
-
},
|
|
11892
|
-
TRUNCATED_EXPLICIT_VR_HEADER: {
|
|
11893
|
-
code: FATAL_CODES.INVALID_FILE_META,
|
|
11894
|
-
message: "Truncated dataset (Explicit VR header read past buffer end)."
|
|
11895
|
-
},
|
|
11896
|
-
SQ_ITEM_HEADER_TRUNCATED: {
|
|
11897
|
-
code: FATAL_CODES.INVALID_FILE_META,
|
|
11898
|
-
message: "Truncated dataset (SQ item header read past buffer end)."
|
|
11899
|
-
},
|
|
11900
|
-
// Neither the marker's element number nor its length field is here. Both are
|
|
11901
|
-
// read at a position the reader may have desynchronized to, so both are
|
|
11902
|
-
// document content: the length field measured as 1109414477, `"MR B"`.
|
|
11903
|
-
UNEXPECTED_FFFE_AT_DATASET_LEVEL: {
|
|
11904
|
-
code: FATAL_CODES.INVALID_FILE_META,
|
|
11905
|
-
message: "An (FFFE,xxxx) delimitation item appears at Data Set level under Explicit VR, where no sequence is open. Its element number and its length field are withheld; the byte offset locates it."
|
|
11906
|
-
},
|
|
11907
|
-
UNEXPECTED_FFFE_AT_DATASET_ROOT: {
|
|
11908
|
-
code: FATAL_CODES.INVALID_FILE_META,
|
|
11909
|
-
message: "An (FFFE,xxxx) delimitation item appears at Data Set level under Implicit VR LE, where no sequence is open. Its element number is withheld; the byte offset locates it."
|
|
11910
|
-
},
|
|
11911
|
-
UNDEFINED_LENGTH_ON_NON_SQ_EXPLICIT: {
|
|
11912
|
-
code: FATAL_CODES.INVALID_FILE_META,
|
|
11913
|
-
message: "An element with VR={vr} declares undefined length (0xFFFFFFFF) under Explicit VR. PS3.5 2026c permits that for a Sequence (7.5.2 Delimitation of The Sequence of Items), for encapsulated (7FE0,0010) Pixel Data (A.4), and for the UN form CP-246 addresses (6.2.2 Unknown (UN) Value Representation), and this element is none of them. Its tag is withheld; the byte offset locates it."
|
|
11914
|
-
},
|
|
11915
|
-
UNDEFINED_LENGTH_ON_NON_SQ_IMPLICIT: {
|
|
11916
|
-
code: FATAL_CODES.INVALID_FILE_META,
|
|
11917
|
-
message: "An element whose VR resolved to {vr} declares undefined length (0xFFFFFFFF) under Implicit VR LE, and the descent as an Implicit VR LE item stream (PS3.5 2026c 6.2.2, the UN form CP-246 addresses) did not succeed. Its tag is withheld; the byte offset locates it."
|
|
11918
|
-
},
|
|
11919
|
-
ELEMENT_LENGTH_EXCEEDS_BUFFER: {
|
|
11920
|
-
code: FATAL_CODES.INVALID_FILE_META,
|
|
11921
|
-
message: "An element declares a Value Length reaching past the end of the bytes being read. Its tag, its declared length and the count of bytes that remain are withheld; the byte offset locates it."
|
|
11922
|
-
},
|
|
11923
|
-
UNEXPECTED_TAG_INSIDE_SEQUENCE: {
|
|
11924
|
-
code: FATAL_CODES.INVALID_FILE_META,
|
|
11925
|
-
message: "A sequence's item stream holds a tag that is neither (FFFE,E000) Item nor (FFFE,E0DD) Sequence Delimitation Item (PS3.5 7.5). That tag is withheld: a value being read as an item stream makes its four bytes document content. The byte offset locates it."
|
|
11926
|
-
},
|
|
11927
|
-
ENCAPSULATED_FRAGMENT_EXCEEDS_BUFFER: {
|
|
11928
|
-
code: FATAL_CODES.INVALID_FILE_META,
|
|
11929
|
-
message: "An encapsulated Pixel Data fragment declares a length reaching past the end of the bytes being read. The declared length is withheld; the byte offset locates the fragment."
|
|
11930
|
-
},
|
|
11931
|
-
ITEM_LENGTH_EXCEEDS_BUFFER: {
|
|
11932
|
-
code: FATAL_CODES.INVALID_FILE_META,
|
|
11933
|
-
message: "An (FFFE,E000) Item declares a length reaching past the end of the bytes being read. The declared length is withheld; the byte offset locates the item."
|
|
11934
|
-
},
|
|
11935
|
-
SQ_NESTING_DEPTH_EXCEEDED: {
|
|
11936
|
-
code: FATAL_CODES.INVALID_FILE_META,
|
|
11937
|
-
message: "SQ nesting depth exceeds {n}."
|
|
11938
|
-
},
|
|
11939
|
-
INFLATED_PAYLOAD_EXCEEDS_CAP: {
|
|
11940
|
-
code: FATAL_CODES.INVALID_FILE_META,
|
|
11941
|
-
message: "Inflated Deflated TS payload exceeds {n}-byte cap."
|
|
11942
|
-
},
|
|
11943
|
-
// `{zlib}` is a member of the nine-name `zlib.codes` table or nothing. zlib's
|
|
11944
|
-
// own `err.message` is never forwarded: it is a string from a library handed
|
|
11945
|
-
// the sender's bytes, which is the one shape of third-party text this parser
|
|
11946
|
-
// cannot vouch for.
|
|
11947
|
-
INFLATE_FAILED: {
|
|
11948
|
-
code: FATAL_CODES.INVALID_FILE_META,
|
|
11949
|
-
message: "Failed to inflate Deflated TS payload (zlib error code: {zlib})."
|
|
11950
|
-
}
|
|
11951
|
-
});
|
|
11952
|
-
function renderTransferSyntax(ts) {
|
|
11953
|
-
if (ts === void 0) return "The Transfer Syntax UID";
|
|
11954
|
-
const name = uid(ts)?.name ?? "";
|
|
11955
|
-
return name.length > 0 ? `Transfer Syntax ${name}` : "The Transfer Syntax UID";
|
|
11956
|
-
}
|
|
11957
|
-
function renderZlibCode(code) {
|
|
11958
|
-
return code !== void 0 && ZLIB_CODES.has(code) ? code : WITHHELD;
|
|
11959
|
-
}
|
|
11960
|
-
function build(key, byteOffset, offsetFrame, snippet, tokens = {}) {
|
|
11961
|
-
const entry = FATAL_MESSAGES[key];
|
|
11962
|
-
const message = entry.message.replace("{vr}", renderVr(tokens.vr)).replace("{ts}", renderTransferSyntax(tokens.ts)).replace("{zlib}", renderZlibCode(tokens.zlib)).replace("{n}", String(tokens.n ?? 0));
|
|
11963
|
-
return new DicomParseError(entry.code, message, byteOffset, offsetFrame, snippet);
|
|
11964
|
-
}
|
|
11965
|
-
function at(key, frame, offset, tokens = {}) {
|
|
11966
|
-
return build(key, offset, frame.name, buildSnippet(frame.buffer, offset), tokens);
|
|
11967
|
-
}
|
|
11968
|
-
function emptyInput() {
|
|
11969
|
-
return build("EMPTY_INPUT", 0, OFFSET_FRAMES.INPUT, "");
|
|
11970
|
-
}
|
|
11971
|
-
function emptyInputAfterNormalization() {
|
|
11972
|
-
return build("EMPTY_INPUT_AFTER_NORMALIZATION", 0, OFFSET_FRAMES.INPUT, "");
|
|
11973
|
-
}
|
|
11974
|
-
function notDicomPart10Required(frame, offset) {
|
|
11975
|
-
return at("NOT_DICOM_PART_10_REQUIRED", frame, offset);
|
|
11976
|
-
}
|
|
11977
|
-
function notDicomPart10(frame, offset) {
|
|
11978
|
-
return at("NOT_DICOM_PART_10", frame, offset);
|
|
11979
|
-
}
|
|
11980
|
-
function unsupportedTransferSyntax(frame, offset, ts) {
|
|
11981
|
-
const name = uid(ts)?.name ?? "";
|
|
11982
|
-
return build(
|
|
11983
|
-
"UNSUPPORTED_TRANSFER_SYNTAX",
|
|
11984
|
-
offset,
|
|
11985
|
-
frame.name,
|
|
11986
|
-
name.length > 0 ? name : buildSnippet(frame.buffer, offset),
|
|
11987
|
-
{ ts }
|
|
11988
|
-
);
|
|
11989
|
-
}
|
|
11990
|
-
function fileMetaTruncated(frame, offset) {
|
|
11991
|
-
return at("FILE_META_TRUNCATED", frame, offset);
|
|
11992
|
-
}
|
|
11993
|
-
function fileMetaGroupLengthOverruns(frame, offset) {
|
|
11994
|
-
return at("FILE_META_GROUP_LENGTH_OVERRUNS", frame, offset);
|
|
11995
|
-
}
|
|
11996
|
-
function fileMetaTransferSyntaxMissing(frame, offset) {
|
|
11997
|
-
return at("FILE_META_TRANSFER_SYNTAX_MISSING", frame, offset);
|
|
11998
|
-
}
|
|
11999
|
-
function truncatedDatasetHeader(frame, offset) {
|
|
12000
|
-
return at("TRUNCATED_DATASET_HEADER", frame, offset);
|
|
12001
|
-
}
|
|
12002
|
-
function truncatedFffeHeader(frame, offset) {
|
|
12003
|
-
return at("TRUNCATED_FFFE_HEADER", frame, offset);
|
|
12004
|
-
}
|
|
12005
|
-
function truncatedExplicitVrHeader(frame, offset) {
|
|
12006
|
-
return at("TRUNCATED_EXPLICIT_VR_HEADER", frame, offset);
|
|
12007
|
-
}
|
|
12008
|
-
function sqItemHeaderTruncated(frame, offset) {
|
|
12009
|
-
return at("SQ_ITEM_HEADER_TRUNCATED", frame, offset);
|
|
12010
|
-
}
|
|
12011
|
-
function unexpectedFffeAtDatasetLevel(frame, offset) {
|
|
12012
|
-
return at("UNEXPECTED_FFFE_AT_DATASET_LEVEL", frame, offset);
|
|
12013
|
-
}
|
|
12014
|
-
function unexpectedFffeAtDatasetRoot(frame, offset) {
|
|
12015
|
-
return at("UNEXPECTED_FFFE_AT_DATASET_ROOT", frame, offset);
|
|
12016
|
-
}
|
|
12017
|
-
function undefinedLengthOnNonSqExplicit(frame, offset, vr) {
|
|
12018
|
-
return at("UNDEFINED_LENGTH_ON_NON_SQ_EXPLICIT", frame, offset, { vr });
|
|
12019
|
-
}
|
|
12020
|
-
function undefinedLengthOnNonSqImplicit(frame, offset, vr) {
|
|
12021
|
-
return at("UNDEFINED_LENGTH_ON_NON_SQ_IMPLICIT", frame, offset, { vr });
|
|
12022
|
-
}
|
|
12023
|
-
function elementLengthExceedsBuffer(frame, offset) {
|
|
12024
|
-
return at("ELEMENT_LENGTH_EXCEEDS_BUFFER", frame, offset);
|
|
12025
|
-
}
|
|
12026
|
-
function unexpectedTagInsideSequence(frame, offset) {
|
|
12027
|
-
return at("UNEXPECTED_TAG_INSIDE_SEQUENCE", frame, offset);
|
|
12028
|
-
}
|
|
12029
|
-
function encapsulatedFragmentExceedsBuffer(frame, offset) {
|
|
12030
|
-
return at("ENCAPSULATED_FRAGMENT_EXCEEDS_BUFFER", frame, offset);
|
|
12031
|
-
}
|
|
12032
|
-
function itemLengthExceedsBuffer(frame, offset) {
|
|
12033
|
-
return at("ITEM_LENGTH_EXCEEDS_BUFFER", frame, offset);
|
|
12034
|
-
}
|
|
12035
|
-
function sqNestingDepthExceeded(frame, offset, limit) {
|
|
12036
|
-
return at("SQ_NESTING_DEPTH_EXCEEDED", frame, offset, { n: limit });
|
|
12037
|
-
}
|
|
12038
|
-
function inflatedPayloadExceedsCap(frame, offset, cap) {
|
|
12039
|
-
return at("INFLATED_PAYLOAD_EXCEEDS_CAP", frame, offset, { n: cap });
|
|
12040
|
-
}
|
|
12041
|
-
function inflateFailed(frame, offset, code) {
|
|
12042
|
-
return at("INFLATE_FAILED", frame, offset, ...code !== void 0 ? [{ zlib: code }] : []);
|
|
12043
|
-
}
|
|
12044
|
-
function copyValueBytes(src) {
|
|
12045
|
-
const out = Buffer.allocUnsafeSlow(src.length);
|
|
12046
|
-
src.copy(out);
|
|
12047
|
-
return out;
|
|
12048
|
-
}
|
|
12049
|
-
var ByteCursor = class {
|
|
12050
|
-
buffer;
|
|
12051
|
-
littleEndian;
|
|
12052
|
-
position;
|
|
12053
|
-
/**
|
|
12054
|
-
* Construct a new cursor at `position` (default 0) over `buffer` with
|
|
12055
|
-
* the given endian orientation.
|
|
12056
|
-
*
|
|
12057
|
-
* @internal
|
|
12058
|
-
*/
|
|
12059
|
-
constructor(buffer, littleEndian, position = 0) {
|
|
12060
|
-
this.buffer = buffer;
|
|
12061
|
-
this.littleEndian = littleEndian;
|
|
12062
|
-
this.position = position;
|
|
12063
|
-
}
|
|
12064
|
-
/** Read a 16-bit unsigned integer at the current position; advance by 2. */
|
|
12065
|
-
readUInt16() {
|
|
12066
|
-
if (this.position + 2 > this.buffer.length) {
|
|
12067
|
-
throw new RangeError("ByteCursor: read past end of buffer");
|
|
12068
|
-
}
|
|
12069
|
-
const v = this.littleEndian ? this.buffer.readUInt16LE(this.position) : this.buffer.readUInt16BE(this.position);
|
|
12070
|
-
this.position += 2;
|
|
12071
|
-
return v;
|
|
12072
|
-
}
|
|
12073
|
-
/** Read a 32-bit unsigned integer at the current position; advance by 4. */
|
|
12074
|
-
readUInt32() {
|
|
12075
|
-
if (this.position + 4 > this.buffer.length) {
|
|
12076
|
-
throw new RangeError("ByteCursor: read past end of buffer");
|
|
12077
|
-
}
|
|
12078
|
-
const v = this.littleEndian ? this.buffer.readUInt32LE(this.position) : this.buffer.readUInt32BE(this.position);
|
|
12079
|
-
this.position += 4;
|
|
12080
|
-
return v;
|
|
12081
|
-
}
|
|
12082
|
-
/** Read a 16-bit unsigned integer at an explicit offset; cursor unchanged. */
|
|
12083
|
-
readUInt16At(offset) {
|
|
12084
|
-
if (offset < 0 || offset + 2 > this.buffer.length) {
|
|
12085
|
-
throw new RangeError("ByteCursor: read past end of buffer");
|
|
12086
|
-
}
|
|
12087
|
-
return this.littleEndian ? this.buffer.readUInt16LE(offset) : this.buffer.readUInt16BE(offset);
|
|
12088
|
-
}
|
|
12089
|
-
/** Read a 32-bit unsigned integer at an explicit offset; cursor unchanged. */
|
|
12090
|
-
readUInt32At(offset) {
|
|
12091
|
-
if (offset < 0 || offset + 4 > this.buffer.length) {
|
|
12092
|
-
throw new RangeError("ByteCursor: read past end of buffer");
|
|
12093
|
-
}
|
|
12094
|
-
return this.littleEndian ? this.buffer.readUInt32LE(offset) : this.buffer.readUInt32BE(offset);
|
|
12095
|
-
}
|
|
12096
|
-
/**
|
|
12097
|
-
* Take a `length`-byte view starting at the current position; advance
|
|
12098
|
-
* the cursor by `length`. Returns a `Buffer.subarray` (zero-copy view);
|
|
12099
|
-
* callers wanting a copy must `Buffer.from(slice)` themselves.
|
|
12100
|
-
*/
|
|
12101
|
-
slice(length) {
|
|
12102
|
-
if (length < 0 || this.position + length > this.buffer.length) {
|
|
12103
|
-
throw new RangeError("ByteCursor: read past end of buffer");
|
|
12104
|
-
}
|
|
12105
|
-
const out = this.buffer.subarray(this.position, this.position + length);
|
|
12106
|
-
this.position += length;
|
|
12107
|
-
return out;
|
|
12108
|
-
}
|
|
12109
|
-
/** Bytes remaining between the current position and the end of the buffer. */
|
|
12110
|
-
remaining() {
|
|
12111
|
-
return this.buffer.length - this.position;
|
|
12112
|
-
}
|
|
12113
|
-
};
|
|
12114
|
-
|
|
12115
|
-
// src/dataset/vr/charset.ts
|
|
12116
|
-
var TERM_TO_LABEL = /* @__PURE__ */ new Map([
|
|
12117
|
-
// Default repertoire (ISO 646 IRV / ASCII). Latin-1 is a lenient,
|
|
12118
|
-
// never-throws 1:1 superset for the ASCII range.
|
|
12119
|
-
["", "latin1"],
|
|
12120
|
-
["ISO_IR 6", "latin1"],
|
|
12121
|
-
["ISO 2022 IR 6", "latin1"],
|
|
12122
|
-
// Single-byte Latin / Cyrillic / Arabic / Greek / Hebrew / Thai.
|
|
12123
|
-
["ISO_IR 100", "latin1"],
|
|
12124
|
-
["ISO 2022 IR 100", "latin1"],
|
|
12125
|
-
["ISO_IR 101", "iso-8859-2"],
|
|
12126
|
-
["ISO 2022 IR 101", "iso-8859-2"],
|
|
12127
|
-
["ISO_IR 109", "iso-8859-3"],
|
|
12128
|
-
["ISO 2022 IR 109", "iso-8859-3"],
|
|
12129
|
-
["ISO_IR 110", "iso-8859-4"],
|
|
12130
|
-
["ISO 2022 IR 110", "iso-8859-4"],
|
|
12131
|
-
["ISO_IR 144", "iso-8859-5"],
|
|
12132
|
-
["ISO 2022 IR 144", "iso-8859-5"],
|
|
12133
|
-
["ISO_IR 127", "iso-8859-6"],
|
|
12134
|
-
["ISO 2022 IR 127", "iso-8859-6"],
|
|
12135
|
-
["ISO_IR 126", "iso-8859-7"],
|
|
12136
|
-
["ISO 2022 IR 126", "iso-8859-7"],
|
|
12137
|
-
["ISO_IR 138", "iso-8859-8"],
|
|
12138
|
-
["ISO 2022 IR 138", "iso-8859-8"],
|
|
12139
|
-
["ISO_IR 148", "iso-8859-9"],
|
|
12140
|
-
["ISO 2022 IR 148", "iso-8859-9"],
|
|
12141
|
-
["ISO_IR 203", "iso-8859-15"],
|
|
12142
|
-
["ISO 2022 IR 203", "iso-8859-15"],
|
|
12143
|
-
["ISO_IR 13", "shift_jis"],
|
|
12144
|
-
["ISO 2022 IR 13", "shift_jis"],
|
|
12145
|
-
["ISO_IR 166", "windows-874"],
|
|
12146
|
-
["ISO 2022 IR 166", "windows-874"],
|
|
12147
|
-
// Unicode / Chinese single-shot.
|
|
12148
|
-
["ISO_IR 192", "utf-8"],
|
|
12149
|
-
["GB18030", "gb18030"],
|
|
12150
|
-
["GBK", "gbk"],
|
|
12151
|
-
// Multibyte code-extension terms (no bare ISO_IR form).
|
|
12152
|
-
["ISO 2022 IR 87", "iso-2022-jp"],
|
|
12153
|
-
["ISO 2022 IR 159", "iso-2022-jp"],
|
|
12154
|
-
["ISO 2022 IR 149", "euc-kr"],
|
|
12155
|
-
["ISO 2022 IR 58", "gb18030"]
|
|
12156
|
-
]);
|
|
12157
|
-
var MULTIBYTE_LABELS = /* @__PURE__ */ new Set([
|
|
12158
|
-
"utf-8",
|
|
12159
|
-
"iso-2022-jp",
|
|
12160
|
-
"euc-kr",
|
|
12161
|
-
"gb18030",
|
|
12162
|
-
"gbk",
|
|
12163
|
-
"shift_jis"
|
|
12164
|
-
]);
|
|
12165
|
-
function parseSpecificCharacterSet(bytes) {
|
|
12166
|
-
const raw = bytes.toString("latin1");
|
|
12167
|
-
return raw.split("\\").map((t) => t.replace(/[ ]+$/u, "").replace(/^[ ]+/u, "")).map((t) => t === "" || TERM_TO_LABEL.has(t) ? t : WITHHELD);
|
|
12168
|
-
}
|
|
12169
|
-
function isKnownCharsetTerm(term) {
|
|
12170
|
-
return TERM_TO_LABEL.has(term);
|
|
12171
|
-
}
|
|
12172
|
-
function resolveDecoderLabel(terms) {
|
|
12173
|
-
if (terms === void 0 || terms.length === 0) return "latin1";
|
|
12174
|
-
let firstKnown;
|
|
12175
|
-
for (const term of terms) {
|
|
12176
|
-
const label = TERM_TO_LABEL.get(term);
|
|
12177
|
-
if (label === void 0) continue;
|
|
12178
|
-
if (MULTIBYTE_LABELS.has(label)) return label;
|
|
12179
|
-
firstKnown ??= label;
|
|
12180
|
-
}
|
|
12181
|
-
return firstKnown ?? "latin1";
|
|
12182
|
-
}
|
|
12183
|
-
function decodeText(bytes, terms) {
|
|
12184
|
-
const label = resolveDecoderLabel(terms);
|
|
12185
|
-
try {
|
|
12186
|
-
return new TextDecoder(label, { fatal: false }).decode(bytes);
|
|
12187
|
-
} catch {
|
|
12188
|
-
try {
|
|
12189
|
-
return new TextDecoder("utf-8", { fatal: false }).decode(bytes);
|
|
12190
|
-
} catch {
|
|
12191
|
-
return bytes.toString("latin1");
|
|
12192
|
-
}
|
|
12193
|
-
}
|
|
12194
|
-
}
|
|
12195
|
-
|
|
12196
11887
|
// src/parser/warnings.ts
|
|
12197
11888
|
var WARNING_CODES = {
|
|
12198
|
-
// ===
|
|
11889
|
+
// === The parser actively emits these (alphabetical within prefix) ===
|
|
11890
|
+
DICOM_DIRECTORY_OFFSET_DEFLATED: "DICOM_DIRECTORY_OFFSET_DEFLATED",
|
|
11891
|
+
DICOM_DIRECTORY_OFFSET_MALFORMED: "DICOM_DIRECTORY_OFFSET_MALFORMED",
|
|
11892
|
+
DICOM_DIRECTORY_OFFSET_UNRESOLVED: "DICOM_DIRECTORY_OFFSET_UNRESOLVED",
|
|
11893
|
+
DICOM_DIRECTORY_RECORD_REVISITED: "DICOM_DIRECTORY_RECORD_REVISITED",
|
|
12199
11894
|
DICOM_DUPLICATE_FILE_META_ELEMENT: "DICOM_DUPLICATE_FILE_META_ELEMENT",
|
|
12200
11895
|
DICOM_DUPLICATE_TAG_IN_DATA_SET: "DICOM_DUPLICATE_TAG_IN_DATA_SET",
|
|
12201
11896
|
DICOM_EMPTY_ITEM_IN_SEQUENCE: "DICOM_EMPTY_ITEM_IN_SEQUENCE",
|
|
@@ -12207,13 +11902,14 @@ var WARNING_CODES = {
|
|
|
12207
11902
|
DICOM_MISSING_PREAMBLE: "DICOM_MISSING_PREAMBLE",
|
|
12208
11903
|
DICOM_NONZERO_RESERVED_BYTES: "DICOM_NONZERO_RESERVED_BYTES",
|
|
12209
11904
|
DICOM_ODD_LENGTH_VALUE_PADDED: "DICOM_ODD_LENGTH_VALUE_PADDED",
|
|
11905
|
+
DICOM_PIXEL_DATA_FRAGMENTS_NOT_DELIMITED: "DICOM_PIXEL_DATA_FRAGMENTS_NOT_DELIMITED",
|
|
12210
11906
|
DICOM_PIXEL_DATA_LENGTH_MISMATCH: "DICOM_PIXEL_DATA_LENGTH_MISMATCH",
|
|
12211
11907
|
DICOM_PRIVATE_TAG_NO_CREATOR: "DICOM_PRIVATE_TAG_NO_CREATOR",
|
|
12212
11908
|
DICOM_SQ_NOT_DESCENDED: "DICOM_SQ_NOT_DESCENDED",
|
|
12213
11909
|
DICOM_UN_PARSED_AS_SQ: "DICOM_UN_PARSED_AS_SQ",
|
|
12214
11910
|
DICOM_UNDEFINED_LENGTH_IN_EXPLICIT_VR: "DICOM_UNDEFINED_LENGTH_IN_EXPLICIT_VR",
|
|
12215
11911
|
DICOM_VR_MISMATCH: "DICOM_VR_MISMATCH",
|
|
12216
|
-
// === VR-decode-time codes (declared
|
|
11912
|
+
// === VR-decode-time codes (declared here; the lazy value decoders fire them) ===
|
|
12217
11913
|
DICOM_BOM_IN_TEXT_VR: "DICOM_BOM_IN_TEXT_VR",
|
|
12218
11914
|
DICOM_DA_LEGACY_FORMAT: "DICOM_DA_LEGACY_FORMAT",
|
|
12219
11915
|
DICOM_DT_NONSTANDARD_OFFSET: "DICOM_DT_NONSTANDARD_OFFSET",
|
|
@@ -12221,14 +11917,29 @@ var WARNING_CODES = {
|
|
|
12221
11917
|
DICOM_NON_ASCII_IN_ASCII_VR: "DICOM_NON_ASCII_IN_ASCII_VR",
|
|
12222
11918
|
DICOM_TRAILING_NULL_IN_TEXT_VR: "DICOM_TRAILING_NULL_IN_TEXT_VR",
|
|
12223
11919
|
DICOM_UI_TRAILING_SPACE: "DICOM_UI_TRAILING_SPACE",
|
|
12224
|
-
// ===
|
|
11920
|
+
// === Charset-decode codes (declared here; the text decoders fire them) ===
|
|
12225
11921
|
DICOM_CHARSET_AMBIGUOUS_SEPARATOR: "DICOM_CHARSET_AMBIGUOUS_SEPARATOR",
|
|
11922
|
+
DICOM_CHARSET_BYTES_UNDECODABLE: "DICOM_CHARSET_BYTES_UNDECODABLE",
|
|
11923
|
+
DICOM_CHARSET_ESCAPE_UNDECLARED: "DICOM_CHARSET_ESCAPE_UNDECLARED",
|
|
11924
|
+
DICOM_CHARSET_EXTENSION_NOT_RESET: "DICOM_CHARSET_EXTENSION_NOT_RESET",
|
|
12226
11925
|
DICOM_UNSUPPORTED_CHARSET: "DICOM_UNSUPPORTED_CHARSET",
|
|
12227
|
-
// ===
|
|
11926
|
+
// === Declared here, emitted elsewhere or not yet emitted at all ===
|
|
12228
11927
|
DICOM_BURNED_IN_ANNOTATION_NOT_REMOVED: "DICOM_BURNED_IN_ANNOTATION_NOT_REMOVED",
|
|
12229
|
-
//
|
|
11928
|
+
// emitted by deidentify(), never by the parser
|
|
11929
|
+
DICOM_DEIDENT_DATES_NOT_TRANSFORMED: "DICOM_DEIDENT_DATES_NOT_TRANSFORMED",
|
|
11930
|
+
// emitted by deidentify(), never by the parser
|
|
11931
|
+
DICOM_DEIDENT_DICOMDIR_FILE_SET_NOT_DISCHARGED: "DICOM_DEIDENT_DICOMDIR_FILE_SET_NOT_DISCHARGED",
|
|
11932
|
+
// emitted by deidentify(), never by the parser
|
|
12230
11933
|
DICOM_DEIDENT_EMBEDDED_ATTRIBUTE_REMOVED: "DICOM_DEIDENT_EMBEDDED_ATTRIBUTE_REMOVED",
|
|
12231
11934
|
// emitted by deidentify(), never by the parser
|
|
11935
|
+
DICOM_DEIDENT_FILE_META_REPLACED: "DICOM_DEIDENT_FILE_META_REPLACED",
|
|
11936
|
+
// emitted by deidentify(), never by the parser
|
|
11937
|
+
DICOM_DEIDENT_GROUP_0004_REMOVED: "DICOM_DEIDENT_GROUP_0004_REMOVED",
|
|
11938
|
+
// emitted by deidentify(), never by the parser
|
|
11939
|
+
DICOM_DEIDENT_METHOD_CODES_PRIOR_REPLACED: "DICOM_DEIDENT_METHOD_CODES_PRIOR_REPLACED",
|
|
11940
|
+
// emitted by deidentify(), never by the parser
|
|
11941
|
+
DICOM_DEIDENT_METHOD_CODES_PRIOR_RETAINED: "DICOM_DEIDENT_METHOD_CODES_PRIOR_RETAINED",
|
|
11942
|
+
// emitted by deidentify(), never by the parser
|
|
12232
11943
|
DICOM_DEIDENT_METHOD_NOT_ADDED: "DICOM_DEIDENT_METHOD_NOT_ADDED",
|
|
12233
11944
|
// emitted by deidentify(), never by the parser
|
|
12234
11945
|
DICOM_DEIDENT_METHOD_NOT_LO: "DICOM_DEIDENT_METHOD_NOT_LO",
|
|
@@ -12237,12 +11948,18 @@ var WARNING_CODES = {
|
|
|
12237
11948
|
// emitted by deidentify(), never by the parser
|
|
12238
11949
|
DICOM_DEIDENT_METHOD_VALUE_OVER_LENGTH: "DICOM_DEIDENT_METHOD_VALUE_OVER_LENGTH",
|
|
12239
11950
|
// emitted by deidentify(), never by the parser
|
|
11951
|
+
DICOM_DEIDENT_PRIVATE_CARRIER_NOT_AUDITABLE: "DICOM_DEIDENT_PRIVATE_CARRIER_NOT_AUDITABLE",
|
|
11952
|
+
// emitted by deidentify(), never by the parser
|
|
11953
|
+
DICOM_DEIDENT_PRIVATE_DECLARATION_NOT_RESOLVED: "DICOM_DEIDENT_PRIVATE_DECLARATION_NOT_RESOLVED",
|
|
11954
|
+
// emitted by deidentify(), never by the parser
|
|
12240
11955
|
DICOM_DEIDENT_SEQUENCE_NOT_AUDITABLE: "DICOM_DEIDENT_SEQUENCE_NOT_AUDITABLE",
|
|
12241
11956
|
// emitted by deidentify(), never by the parser
|
|
12242
11957
|
DICOM_DEIDENT_UNDEFINED_VR_NOT_AUDITABLE: "DICOM_DEIDENT_UNDEFINED_VR_NOT_AUDITABLE",
|
|
12243
11958
|
// emitted by deidentify(), never by the parser
|
|
11959
|
+
DICOM_DEIDENT_UNREGISTERED_ELEMENT_REMOVED: "DICOM_DEIDENT_UNREGISTERED_ELEMENT_REMOVED",
|
|
11960
|
+
// emitted by deidentify(), never by the parser
|
|
12244
11961
|
DICOM_PRIVATE_CREATOR_UNKNOWN: "DICOM_PRIVATE_CREATOR_UNKNOWN"
|
|
12245
|
-
//
|
|
11962
|
+
// emitted only when a profile is active
|
|
12246
11963
|
};
|
|
12247
11964
|
var WARNING_MESSAGES = Object.freeze({
|
|
12248
11965
|
DICOM_MISSING_PREAMBLE: "No DICM magic at offset 128; falling back to offset-0 dataset.",
|
|
@@ -12329,6 +12046,17 @@ var WARNING_MESSAGES = Object.freeze({
|
|
|
12329
12046
|
// count, so a conformant 64-character Value can exceed 64 bytes under a
|
|
12330
12047
|
// single-byte repertoire too. The message states what was measured.
|
|
12331
12048
|
DICOM_DEIDENT_METHOD_VALUE_OVER_LENGTH: "The De-identification Method (0012,0063) this run wrote carries a Value longer than 64 bytes. PS3.5 Table 6.2-1 bounds an LO Value at 64 characters, per Value and not per Value Field, and PS3.5 6.2 specifies that length in characters rather than bytes and excludes Code Extension escape sequences from the count: a Value of 64 bytes or fewer can never carry more than 64 characters, but a longer one is not necessarily over the maximum. This run never shortens, splits or truncates a Value it did not compose: a caller-supplied method, and a value the source file already carried, are both written through as given. A receiver that enforces the VR may reject the attribute that records the de-identification. The value, its length, how many Values are over and which of them came from where are all withheld from this message.",
|
|
12049
|
+
// Once per run, and no value, no count and no VR: the kept Items are the
|
|
12050
|
+
// file's own bytes, and how many there were is a count over input. The tags in
|
|
12051
|
+
// the text are constants of this code. It is the (0012,0064) sibling of
|
|
12052
|
+
// DICOM_DEIDENT_METHOD_PRIOR_RETAINED and deliberately not that code widened:
|
|
12053
|
+
// that one's published meaning names (0012,0063).
|
|
12054
|
+
DICOM_DEIDENT_METHOD_CODES_PRIOR_RETAINED: "One or more Items of a De-identification Method Code Sequence (0012,0064) the source file already carried were kept, in their original order, ahead of the codes this run added, as PS3.15 E.1.1 requires. Neither that attribute nor the Code Value, Coding Scheme Designator and Code Meaning inside its Items has a Table E.1-1 row, so those bytes are in the output as the sender wrote them, under (0012,0062) = YES, and no code in them was checked against CID 7050. If your source may put identifying text there, read (0012,0064) off the de-identified dataset and decide for yourself. The Items' content and their count are withheld from this message.",
|
|
12055
|
+
// Once per run. No value, no length AND NO VR, for the reason
|
|
12056
|
+
// DICOM_DEIDENT_METHOD_NOT_LO states: the VR is two bytes read from the file,
|
|
12057
|
+
// and a fabricated header makes them document content. The text names both
|
|
12058
|
+
// unreadable shapes so that which one fired is not disclosed by the wording.
|
|
12059
|
+
DICOM_DEIDENT_METHOD_CODES_PRIOR_REPLACED: "The De-identification Method Code Sequence (0012,0064) the source file carried was not a Sequence of Items this run could read (it was not encoded as SQ, or its Items were not parsed), so there were no Items to add this run's codes to (PS3.15 E.1.1) and the attribute was replaced with this run's codes alone. The replaced bytes are not in the output; if you need them, read (0012,0064) off the source dataset before de-identifying. Their content and their VR are both withheld from this message.",
|
|
12332
12060
|
// BOTH of the disagreeing length fields are deliberately absent, and the
|
|
12333
12061
|
// second one is the eighth instance of `DICOM-DIAGNOSTIC-PHI-RESIDUALS`: the
|
|
12334
12062
|
// remaining-bytes count this string used to carry was the enclosing sequence's
|
|
@@ -12341,10 +12069,82 @@ var WARNING_MESSAGES = Object.freeze({
|
|
|
12341
12069
|
// over. `{n2}` stays - it is the product this parser computed from the image
|
|
12342
12070
|
// description attributes, not a number it read. The tag is a constant.
|
|
12343
12071
|
DICOM_PIXEL_DATA_LENGTH_MISMATCH: "(7FE0,0010) PixelData declared length does not match the computed {n2} bytes. The declared length is withheld; the byte offset identifies the element.",
|
|
12072
|
+
// No slot at all. The fragments are the sender's encoded pixels, their lengths
|
|
12073
|
+
// are 32-bit wire reads, and how many were read is a count over input, so none
|
|
12074
|
+
// of the three has a place here. The tags are constants of this code, and the
|
|
12075
|
+
// byte offset is the Pixel Data element's own header, which this parser
|
|
12076
|
+
// counted. See `pixelDataFragmentsNotDelimited`.
|
|
12077
|
+
DICOM_PIXEL_DATA_FRAGMENTS_NOT_DELIMITED: "Encapsulated Pixel Data (7FE0,0010) reaches the end of the bytes being read without the Sequence Delimitation Item (FFFE,E0DD) PS3.5 2026c A.4 requires after its last fragment, so the fragments read from it may not be all the sender wrote. No fragment byte, length or count is reproduced here; the byte offset locates the Pixel Data element.",
|
|
12344
12078
|
DICOM_IMPLICIT_VR_FOR_PRIVATE_TAG_WITHOUT_VR: "A private element under Implicit VR LE has no VR override; falling back to UN. Its tag is withheld; the byte offset identifies the element.",
|
|
12345
12079
|
DICOM_PRIVATE_CREATOR_UNKNOWN: "A private element has a Private Creator the active profile's private dictionary does not name; falling back to UN. The creator string is not reproduced here - read the (gggg,00EE) element if you need it. Its tag is withheld; the byte offset identifies the element.",
|
|
12346
12080
|
DICOM_BURNED_IN_ANNOTATION_NOT_REMOVED: "Pixel Data is present and Burned In Annotation is not 'NO'; this metadata-only de-identifier cannot inspect or clean pixels. Recognizable text may remain burned into the image.",
|
|
12081
|
+
// No tag, no count and no value, and none of the three is caution. This code is
|
|
12082
|
+
// raised ONCE PER RUN rather than once per element, so there is no element to
|
|
12083
|
+
// name and no attacker-chosen multiplier on the string: the tags are on
|
|
12084
|
+
// report.fileMetaElementsDropped, where a caller can read them beside the
|
|
12085
|
+
// total. It fires on a perfectly CONFORMANT file - a Sending AE Title is a
|
|
12086
|
+
// legal (0002,xxxx) element - which is why the tags are not here: the
|
|
12087
|
+
// withholding must not depend on the input being malformed.
|
|
12088
|
+
DICOM_DEIDENT_FILE_META_REPLACED: "The File Meta Information group of the de-identified output describes this de-identifying application, not the source file (PS3.15 E.1.1). The Source Application Entity Title and the source's implementation identity are gone, and every (0002,xxxx) element this library does not model was dropped rather than re-emitted, so the byte-for-byte File Meta round trip does NOT hold for this output. See report.fileMetaElementsDropped for what went and how many.",
|
|
12089
|
+
// Once per run, for the same reason and with the same consequence: no tag, no
|
|
12090
|
+
// count, no context path. report.group0004Removals names the elements it could
|
|
12091
|
+
// fit and report.group0004RemovalCount is the complete total.
|
|
12092
|
+
DICOM_DEIDENT_GROUP_0004_REMOVED: "Data Elements with a Group Number of 0004 were removed from this object, as PS3.15 E.1.1 requires of any SOP Instance or DICOM File other than a DICOMDIR File. Their tags and count are withheld from this message; see report.group0004Removals and report.group0004RemovalCount.",
|
|
12093
|
+
// 🩺 Once per run, on the option set alone, and NOT on Dataset.warnings. The
|
|
12094
|
+
// trigger is a choice the caller made rather than anything in the file, so
|
|
12095
|
+
// there is no element to name, no count and no context path; every token below
|
|
12096
|
+
// is a clause reference or a published option name. It states the half of
|
|
12097
|
+
// PS3.15 E.3.6 this library does not perform, which is the half a recipient
|
|
12098
|
+
// reading MODIFIED would otherwise assume was performed.
|
|
12099
|
+
DICOM_DEIDENT_DATES_NOT_TRANSFORMED: "The Retain Longitudinal Temporal Information With Modified Dates Option was active, so this run resolved Table E.1-1's modified-dates column and wrote (0028,0303) = MODIFIED. It did NOT modify any date or time value: PS3.15 E.3.6 also requires the dates themselves to be modified and the manner of modification to be described in a Conformance Statement, and this library performs no date transformation and states no Conformance Statement. The MODIFIED declaration is true only if you transformed the dates yourself; if you did not, the output makes a claim nobody performed.",
|
|
12100
|
+
// Once per run. The SOP Class UID that selected this branch is a constant of
|
|
12101
|
+
// the code (it is the one value that reaches it), so it is written out; nothing
|
|
12102
|
+
// else about the file is.
|
|
12103
|
+
DICOM_DEIDENT_DICOMDIR_FILE_SET_NOT_DISCHARGED: "This object declares Media Storage SOP Class UID 1.2.840.10008.1.3.10 (Media Storage Directory Storage), so PS3.15 E.1.1's carve-out applies and its (0004,xxxx) Data Elements were NOT removed. Two File-set clauses of that bullet were NOT discharged by this run: no DICOMDIR was created from the de-identified DICOM Files it references, and no non-de-identified DICOMDIR File was removed from the File-set. This library has no view of a File-set, so both are yours to do. Do not treat this output as a File-set-conformant DICOMDIR.",
|
|
12104
|
+
// No slot. The four codes below fire on a DICOMDIR's offset attributes, whose
|
|
12105
|
+
// values are raw 32-bit wire reads, and on records whose keys are the
|
|
12106
|
+
// sender's own, so neither an offset, a record index nor a key has a place
|
|
12107
|
+
// here. `position.byteOffset` locates the attribute (a root one at its
|
|
12108
|
+
// element header, a record's at that record's Item tag) and
|
|
12109
|
+
// `position.contextPath` names which attribute of which record; both are
|
|
12110
|
+
// structure this parser counted.
|
|
12111
|
+
DICOM_DIRECTORY_OFFSET_UNRESOLVED: "A DICOMDIR offset attribute names no Item of the Directory Record Sequence (0004,1220): it is not the file offset of any Directory Record's (FFFE,E000) Item tag (PS3.3 F.3.2.2), so no record was resolved from it and the tree does not follow it. serializeDicom refuses to write it. The offset's value is withheld; the byte offset and context path locate the attribute.",
|
|
12112
|
+
DICOM_DIRECTORY_OFFSET_MALFORMED: "A DICOMDIR offset attribute's Value Length is not 4, so its value is not one 32-bit unsigned integer (UL, VM 1) and no record was resolved from it. serializeDicom refuses to write it. The value and its length are withheld; the byte offset and context path locate the attribute.",
|
|
12113
|
+
DICOM_DIRECTORY_RECORD_REVISITED: "Following a DICOMDIR offset attribute would reach a Directory Record already reached in this walk, so that record is in the tree once and the walk did not follow the offset again. The offset's value is withheld; the byte offset and context path locate the attribute.",
|
|
12114
|
+
DICOM_DIRECTORY_OFFSET_DEFLATED: "This DICOMDIR is encoded in Deflated Explicit VR Little Endian and carries a non-zero Directory Record offset. A byte position inside a deflated stream names no Item a reader can seek to, so no record was resolved from any offset; PS3.10 8.6 requires a DICOMDIR File to use Explicit VR Little Endian. serializeDicom refuses to write it. The byte offset is where the deflated stream begins.",
|
|
12347
12115
|
DICOM_DEIDENT_EMBEDDED_ATTRIBUTE_REMOVED: "Element ({tag}) {vr} was kept by the action table, but its value ends with {n} whole Data Element(s) - an over-declared Value Length swallowed what followed it. Emptied rather than kept, because the action table cannot see an attribute encoded inside a value. report.embeddedAttributes names the ones this run acts on that also have a literal Table E.1-1 row, which may be none of them.",
|
|
12116
|
+
// Deliberately short, for the reason the two codes below it are short: one is
|
|
12117
|
+
// raised per removed private element and the element count is chosen by the
|
|
12118
|
+
// input.
|
|
12119
|
+
//
|
|
12120
|
+
// 🩺 NO BYTE COUNT, AND THAT IS NOT CAUTION - IT IS THE SAME BOUND TAKEN
|
|
12121
|
+
// OUT OF THE TWO CODES BELOW. `Element.rawBytes.length` EQUALS the Value
|
|
12122
|
+
// Length read off the element header, so on a header an under-declared length
|
|
12123
|
+
// upstream composed out of somebody's value the decimal is four document
|
|
12124
|
+
// bytes. The tag survives because `renderTag` is a membership test against
|
|
12125
|
+
// PS3.6's registry, and a private tag - which every element raising this code
|
|
12126
|
+
// carries - renders `<withheld>` there. See `privateCarrierNotAuditable`.
|
|
12127
|
+
//
|
|
12128
|
+
// 🛑 IT SAID "KEPT" UNTIL THE RUN STOPPED KEEPING THE VALUE, AND THE CODE
|
|
12129
|
+
// NAME IS UNCHANGED WHILE THE MEANING IS NOT. Through `0.0.19` this reported a
|
|
12130
|
+
// value the run SHIPPED unexamined; it now reports one the run REMOVED
|
|
12131
|
+
// unexamined. A consumer narrowing on the code keeps compiling and has to
|
|
12132
|
+
// re-read what it means - which is why the wording states the outcome
|
|
12133
|
+
// outright and why the published code SET did not move.
|
|
12134
|
+
DICOM_DEIDENT_PRIVATE_CARRIER_NOT_AUDITABLE: "Element ({tag}) is a Private Attribute a profile vouched for under RetainSafePrivate whose value this run did not enumerate, so any Data Set encoded inside it could not be audited (PS3.15 E.3.10 vouches for the Attribute, not for a Data Set nested in its value; E.1.1). REMOVED rather than retained. The byte count is withheld; see report.unenumerablePrivateRemovals.",
|
|
12135
|
+
// Deliberately short, and one per Item: the Item count is chosen by the
|
|
12136
|
+
// input.
|
|
12137
|
+
//
|
|
12138
|
+
// 🩺 NOT ONE TOKEN OF THE ITEM IS ECHOED, AND EVERY FIELD THAT WOULD BE IS A
|
|
12139
|
+
// DOCUMENT VALUE. The Item's own values are what failed to resolve: a Private
|
|
12140
|
+
// Creator Reference (0008,0302) is an LO the sender wrote, a Private Group
|
|
12141
|
+
// Reference (0008,0301) is a group number read off the wire, and a Block
|
|
12142
|
+
// Identifying Information Status (0008,0303) that reaches this code is by
|
|
12143
|
+
// construction outside the closed set PS3.3 C.12.1 enumerates, so no
|
|
12144
|
+
// membership test can stand behind it. The two tags in the text are constants
|
|
12145
|
+
// of this code rather than substitutions. `position.byteOffset` locates the
|
|
12146
|
+
// (0008,0300) element and is a position this parser counted.
|
|
12147
|
+
DICOM_DEIDENT_PRIVATE_DECLARATION_NOT_RESOLVED: "An Item of Private Data Element Characteristics Sequence (0008,0300) does not resolve to a block of Private Data Elements reserved in this Data Set, so nothing was retained on account of it (PS3.15 E.3.10; PS3.3 C.12.1). Its declared values are withheld: they are the sender's own and are what failed to resolve.",
|
|
12348
12148
|
// Deliberately short. One of these is raised per un-auditable element, so a
|
|
12349
12149
|
// long message is multiplied by an element count the input controls; the
|
|
12350
12150
|
// reasoning belongs in the docs, not in a string repeated thousands of times.
|
|
@@ -12377,6 +12177,16 @@ var WARNING_MESSAGES = Object.freeze({
|
|
|
12377
12177
|
// The byte offset locates the element instead, and is a position this parser
|
|
12378
12178
|
// counted rather than anything the document said.
|
|
12379
12179
|
DICOM_DEIDENT_UNDEFINED_VR_NOT_AUDITABLE: "An element at byte offset {n2} carries an on-wire VR that is not one of the 34 PS3.5 6.2 defines, so its value bytes are not a Value Field this library decoded; emptied (PS3.15 E.1.1). Its tag, VR and byte count are withheld: an earlier under-declared length can make them fragments of some element's value. See report.undefinedVrElements.",
|
|
12180
|
+
// 🩺 Once per run, and NO TAG, NO VR, NO COUNT AND NO CONTEXT PATH, for the
|
|
12181
|
+
// reason DICOM_DEIDENT_UNDEFINED_VR_NOT_AUDITABLE withholds them: the trigger is
|
|
12182
|
+
// "no PS3.6 row carries this tag", which is exactly what four bytes read out of
|
|
12183
|
+
// some element's value look like, so the tag may BE document content. There is
|
|
12184
|
+
// no membership table for a renderer to fall back on here either, because the
|
|
12185
|
+
// condition is the absence of one. The records are on
|
|
12186
|
+
// report.unregisteredElementRemovals (capped, byte offsets only) and the true
|
|
12187
|
+
// total is on report.unregisteredElementRemovalCount. It fires on a CONFORMANT
|
|
12188
|
+
// newer-edition file too, which is the over-redaction the message states.
|
|
12189
|
+
DICOM_DEIDENT_UNREGISTERED_ELEMENT_REMOVED: "Non-private Data Elements whose tags this build's PS3.6 2026d registry does not carry, and which Table E.1-1 does not list, were removed at every depth: a Standard Attribute newer than this build, or one its sender invented, can carry identifying information no Table E.1-1 row names (PS3.15 E.1.1). A conformant attribute from a later edition is removed too. Their tags, VRs and count are withheld from this message; see report.unregisteredElementRemovals and report.unregisteredElementRemovalCount.",
|
|
12380
12190
|
DICOM_BOM_IN_TEXT_VR: "Element ({tag}) {vr} value begins with a UTF-8 BOM; stripped on decode.",
|
|
12381
12191
|
DICOM_TRAILING_NULL_IN_TEXT_VR: "Element ({tag}) {vr} value has a trailing NULL pad where SPACE is expected; trimmed.",
|
|
12382
12192
|
DICOM_UI_TRAILING_SPACE: "Element ({tag}) UI value is SPACE-padded; UI requires NULL padding (PS3.5 \xA76.2). Trimmed.",
|
|
@@ -12385,119 +12195,1060 @@ var WARNING_MESSAGES = Object.freeze({
|
|
|
12385
12195
|
DICOM_DA_LEGACY_FORMAT: "Element ({tag}) DA value is not in canonical YYYYMMDD form; decoded best-effort, raw preserved.",
|
|
12386
12196
|
DICOM_DT_NONSTANDARD_OFFSET: "Element ({tag}) DT value has a non-standard UTC offset; decoded best-effort, raw preserved.",
|
|
12387
12197
|
DICOM_UNSUPPORTED_CHARSET: "(0008,0005) Specific Character Set value {n} names a defined term this build does not support; decoding text as UTF-8 best-effort. The term is not reproduced here - read the element if you need it.",
|
|
12388
|
-
DICOM_CHARSET_AMBIGUOUS_SEPARATOR: "(0008,0005) Specific Character Set value {n} is ambiguous under the active code extensions; decoding text as UTF-8 best-effort."
|
|
12198
|
+
DICOM_CHARSET_AMBIGUOUS_SEPARATOR: "(0008,0005) Specific Character Set value {n} is ambiguous under the active code extensions; decoding text as UTF-8 best-effort.",
|
|
12199
|
+
// The three ISO 2022 code-extension codes take a tag and a VR and nothing
|
|
12200
|
+
// else. The escape sequence, the set it names and the characters around it
|
|
12201
|
+
// are all value bytes, so none of them has a slot here.
|
|
12202
|
+
DICOM_CHARSET_ESCAPE_UNDECLARED: "Element ({tag}) {vr} value switches character set with an ISO 2022 escape sequence for a set that (0008,0005) Specific Character Set does not declare; decoded in the set the escape sequence names.",
|
|
12203
|
+
DICOM_CHARSET_BYTES_UNDECODABLE: "Element ({tag}) {vr} value holds bytes no designated character set decodes (an unrecognized escape sequence, a byte with no set designated for it, or a code its set does not define); they read as U+FFFD in the decoded value. Raw bytes preserved.",
|
|
12204
|
+
DICOM_CHARSET_EXTENSION_NOT_RESET: "Element ({tag}) {vr} value ends a line, a value or a name component without switching back to the (0008,0005) Value 1 character set (PS3.5 6.1.2.5.3); decoded as written, and what follows decodes from Value 1."
|
|
12389
12205
|
});
|
|
12390
|
-
function
|
|
12206
|
+
function build(code, position, tokens = {}) {
|
|
12391
12207
|
const message = WARNING_MESSAGES[code].replace("{tag}", renderTag(tokens.tag)).replace("{vr2}", renderVr(tokens.vr2)).replace("{vr}", renderVr(tokens.vr)).replace("{n2}", String(tokens.n2 ?? 0)).replace("{n}", String(tokens.n ?? 0));
|
|
12392
12208
|
return { code, message, position };
|
|
12393
12209
|
}
|
|
12394
12210
|
function missingPreamble(position) {
|
|
12395
|
-
return
|
|
12211
|
+
return build(WARNING_CODES.DICOM_MISSING_PREAMBLE, position);
|
|
12396
12212
|
}
|
|
12397
12213
|
function fileMetaGroupLengthMissing(position) {
|
|
12398
|
-
return
|
|
12214
|
+
return build(WARNING_CODES.DICOM_FILE_META_GROUP_LENGTH_MISSING, position);
|
|
12399
12215
|
}
|
|
12400
12216
|
function fileMetaGroupLengthMismatch(position, declared, actual) {
|
|
12401
|
-
return
|
|
12217
|
+
return build(WARNING_CODES.DICOM_FILE_META_GROUP_LENGTH_MISMATCH, position, {
|
|
12402
12218
|
n: declared,
|
|
12403
12219
|
n2: actual
|
|
12404
12220
|
});
|
|
12405
12221
|
}
|
|
12406
12222
|
function undefinedLengthInExplicitVR(position, tag) {
|
|
12407
|
-
return
|
|
12223
|
+
return build(WARNING_CODES.DICOM_UNDEFINED_LENGTH_IN_EXPLICIT_VR, position, { tag });
|
|
12408
12224
|
}
|
|
12409
12225
|
function oddLengthValuePadded(position, tag) {
|
|
12410
|
-
return
|
|
12226
|
+
return build(WARNING_CODES.DICOM_ODD_LENGTH_VALUE_PADDED, position, { tag });
|
|
12411
12227
|
}
|
|
12412
12228
|
function vrMismatch(position, tag, dictVR, fileVR) {
|
|
12413
|
-
return
|
|
12229
|
+
return build(WARNING_CODES.DICOM_VR_MISMATCH, position, { tag, vr: dictVR, vr2: fileVR });
|
|
12414
12230
|
}
|
|
12415
12231
|
function privateTagNoCreator(position) {
|
|
12416
|
-
return
|
|
12232
|
+
return build(WARNING_CODES.DICOM_PRIVATE_TAG_NO_CREATOR, position);
|
|
12417
12233
|
}
|
|
12418
12234
|
function groupLengthInDataset(position) {
|
|
12419
|
-
return
|
|
12235
|
+
return build(WARNING_CODES.DICOM_GROUP_LENGTH_IN_DATASET, position);
|
|
12420
12236
|
}
|
|
12421
12237
|
function nonzeroReservedBytes(position) {
|
|
12422
|
-
return
|
|
12238
|
+
return build(WARNING_CODES.DICOM_NONZERO_RESERVED_BYTES, position);
|
|
12423
12239
|
}
|
|
12424
12240
|
function unParsedAsSQ(position, tag) {
|
|
12425
|
-
return
|
|
12241
|
+
return build(WARNING_CODES.DICOM_UN_PARSED_AS_SQ, position, { tag });
|
|
12426
12242
|
}
|
|
12427
12243
|
function sqNotDescended(position, tag) {
|
|
12428
|
-
return
|
|
12244
|
+
return build(WARNING_CODES.DICOM_SQ_NOT_DESCENDED, position, { tag });
|
|
12429
12245
|
}
|
|
12430
12246
|
function itemCrossesSequenceEnd(position, tag) {
|
|
12431
|
-
return
|
|
12247
|
+
return build(WARNING_CODES.DICOM_ITEM_CROSSES_SEQUENCE_END, position, { tag });
|
|
12432
12248
|
}
|
|
12433
12249
|
function emptyItemInSequence(position, tag) {
|
|
12434
|
-
return
|
|
12250
|
+
return build(WARNING_CODES.DICOM_EMPTY_ITEM_IN_SEQUENCE, position, { tag });
|
|
12251
|
+
}
|
|
12252
|
+
function pixelDataFragmentsNotDelimited(position) {
|
|
12253
|
+
return build(WARNING_CODES.DICOM_PIXEL_DATA_FRAGMENTS_NOT_DELIMITED, position);
|
|
12435
12254
|
}
|
|
12436
12255
|
function duplicateTagInDataSet(position) {
|
|
12437
|
-
return
|
|
12256
|
+
return build(WARNING_CODES.DICOM_DUPLICATE_TAG_IN_DATA_SET, position);
|
|
12438
12257
|
}
|
|
12439
12258
|
function duplicateFileMetaElement(position) {
|
|
12440
|
-
return
|
|
12259
|
+
return build(WARNING_CODES.DICOM_DUPLICATE_FILE_META_ELEMENT, position);
|
|
12441
12260
|
}
|
|
12442
12261
|
function implicitVRForPrivateTagWithoutVR(position) {
|
|
12443
|
-
return
|
|
12262
|
+
return build(WARNING_CODES.DICOM_IMPLICIT_VR_FOR_PRIVATE_TAG_WITHOUT_VR, position);
|
|
12444
12263
|
}
|
|
12445
12264
|
function privateCreatorUnknown(position) {
|
|
12446
|
-
return
|
|
12265
|
+
return build(WARNING_CODES.DICOM_PRIVATE_CREATOR_UNKNOWN, position);
|
|
12447
12266
|
}
|
|
12448
12267
|
function burnedInAnnotationNotRemoved(position) {
|
|
12449
|
-
return
|
|
12268
|
+
return build(WARNING_CODES.DICOM_BURNED_IN_ANNOTATION_NOT_REMOVED, position);
|
|
12269
|
+
}
|
|
12270
|
+
function fileMetaReplaced(position) {
|
|
12271
|
+
return build(WARNING_CODES.DICOM_DEIDENT_FILE_META_REPLACED, position);
|
|
12272
|
+
}
|
|
12273
|
+
function group0004Removed(position) {
|
|
12274
|
+
return build(WARNING_CODES.DICOM_DEIDENT_GROUP_0004_REMOVED, position);
|
|
12275
|
+
}
|
|
12276
|
+
function dicomdirFileSetNotDischarged(position) {
|
|
12277
|
+
return build(WARNING_CODES.DICOM_DEIDENT_DICOMDIR_FILE_SET_NOT_DISCHARGED, position);
|
|
12278
|
+
}
|
|
12279
|
+
function directoryOffsetUnresolved(position) {
|
|
12280
|
+
return build(WARNING_CODES.DICOM_DIRECTORY_OFFSET_UNRESOLVED, position);
|
|
12281
|
+
}
|
|
12282
|
+
function directoryOffsetMalformed(position) {
|
|
12283
|
+
return build(WARNING_CODES.DICOM_DIRECTORY_OFFSET_MALFORMED, position);
|
|
12284
|
+
}
|
|
12285
|
+
function directoryRecordRevisited(position) {
|
|
12286
|
+
return build(WARNING_CODES.DICOM_DIRECTORY_RECORD_REVISITED, position);
|
|
12287
|
+
}
|
|
12288
|
+
function directoryOffsetDeflated(position) {
|
|
12289
|
+
return build(WARNING_CODES.DICOM_DIRECTORY_OFFSET_DEFLATED, position);
|
|
12290
|
+
}
|
|
12291
|
+
function datesNotTransformed(position) {
|
|
12292
|
+
return build(WARNING_CODES.DICOM_DEIDENT_DATES_NOT_TRANSFORMED, position);
|
|
12450
12293
|
}
|
|
12451
12294
|
function deidentMethodNotAdded(position) {
|
|
12452
|
-
return
|
|
12295
|
+
return build(WARNING_CODES.DICOM_DEIDENT_METHOD_NOT_ADDED, position);
|
|
12453
12296
|
}
|
|
12454
12297
|
function deidentMethodNotLo(position) {
|
|
12455
|
-
return
|
|
12298
|
+
return build(WARNING_CODES.DICOM_DEIDENT_METHOD_NOT_LO, position);
|
|
12456
12299
|
}
|
|
12457
12300
|
function deidentMethodPriorRetained(position) {
|
|
12458
|
-
return
|
|
12301
|
+
return build(WARNING_CODES.DICOM_DEIDENT_METHOD_PRIOR_RETAINED, position);
|
|
12459
12302
|
}
|
|
12460
12303
|
function deidentMethodValueOverLength(position) {
|
|
12461
|
-
return
|
|
12304
|
+
return build(WARNING_CODES.DICOM_DEIDENT_METHOD_VALUE_OVER_LENGTH, position);
|
|
12305
|
+
}
|
|
12306
|
+
function deidentMethodCodesPriorRetained(position) {
|
|
12307
|
+
return build(WARNING_CODES.DICOM_DEIDENT_METHOD_CODES_PRIOR_RETAINED, position);
|
|
12308
|
+
}
|
|
12309
|
+
function deidentMethodCodesPriorReplaced(position) {
|
|
12310
|
+
return build(WARNING_CODES.DICOM_DEIDENT_METHOD_CODES_PRIOR_REPLACED, position);
|
|
12462
12311
|
}
|
|
12463
12312
|
function embeddedAttributeRemoved(position, tag, vr, count) {
|
|
12464
|
-
return
|
|
12313
|
+
return build(WARNING_CODES.DICOM_DEIDENT_EMBEDDED_ATTRIBUTE_REMOVED, position, {
|
|
12465
12314
|
tag,
|
|
12466
12315
|
vr,
|
|
12467
12316
|
n: count
|
|
12468
12317
|
});
|
|
12469
12318
|
}
|
|
12319
|
+
function privateCarrierNotAuditable(position, tag) {
|
|
12320
|
+
return build(WARNING_CODES.DICOM_DEIDENT_PRIVATE_CARRIER_NOT_AUDITABLE, position, { tag });
|
|
12321
|
+
}
|
|
12322
|
+
function privateDeclarationNotResolved(position) {
|
|
12323
|
+
return build(WARNING_CODES.DICOM_DEIDENT_PRIVATE_DECLARATION_NOT_RESOLVED, position);
|
|
12324
|
+
}
|
|
12470
12325
|
function sequenceNotAuditable(position, tag) {
|
|
12471
|
-
return
|
|
12326
|
+
return build(WARNING_CODES.DICOM_DEIDENT_SEQUENCE_NOT_AUDITABLE, position, { tag });
|
|
12472
12327
|
}
|
|
12473
12328
|
function undefinedVrNotAuditable(position) {
|
|
12474
|
-
return
|
|
12329
|
+
return build(WARNING_CODES.DICOM_DEIDENT_UNDEFINED_VR_NOT_AUDITABLE, position, {
|
|
12475
12330
|
n2: position.byteOffset
|
|
12476
12331
|
});
|
|
12477
12332
|
}
|
|
12333
|
+
function unregisteredElementRemoved(position) {
|
|
12334
|
+
return build(WARNING_CODES.DICOM_DEIDENT_UNREGISTERED_ELEMENT_REMOVED, position);
|
|
12335
|
+
}
|
|
12478
12336
|
function bomInTextVR(position, tag, vr) {
|
|
12479
|
-
return
|
|
12337
|
+
return build(WARNING_CODES.DICOM_BOM_IN_TEXT_VR, position, { tag, vr });
|
|
12480
12338
|
}
|
|
12481
12339
|
function trailingNullInTextVR(position, tag, vr) {
|
|
12482
|
-
return
|
|
12340
|
+
return build(WARNING_CODES.DICOM_TRAILING_NULL_IN_TEXT_VR, position, { tag, vr });
|
|
12483
12341
|
}
|
|
12484
12342
|
function uiTrailingSpace(position, tag) {
|
|
12485
|
-
return
|
|
12343
|
+
return build(WARNING_CODES.DICOM_UI_TRAILING_SPACE, position, { tag });
|
|
12486
12344
|
}
|
|
12487
12345
|
function nonAsciiInAsciiVR(position, tag, vr) {
|
|
12488
|
-
return
|
|
12346
|
+
return build(WARNING_CODES.DICOM_NON_ASCII_IN_ASCII_VR, position, { tag, vr });
|
|
12347
|
+
}
|
|
12348
|
+
function isNonintegerValue(position, tag) {
|
|
12349
|
+
return build(WARNING_CODES.DICOM_IS_NONINTEGER_VALUE, position, { tag });
|
|
12350
|
+
}
|
|
12351
|
+
function daLegacyFormat(position, tag) {
|
|
12352
|
+
return build(WARNING_CODES.DICOM_DA_LEGACY_FORMAT, position, { tag });
|
|
12353
|
+
}
|
|
12354
|
+
function dtNonstandardOffset(position, tag) {
|
|
12355
|
+
return build(WARNING_CODES.DICOM_DT_NONSTANDARD_OFFSET, position, { tag });
|
|
12356
|
+
}
|
|
12357
|
+
function unsupportedCharset(position, valueIndex) {
|
|
12358
|
+
return build(WARNING_CODES.DICOM_UNSUPPORTED_CHARSET, position, { n: valueIndex });
|
|
12359
|
+
}
|
|
12360
|
+
function charsetEscapeUndeclared(position, tag, vr) {
|
|
12361
|
+
return build(WARNING_CODES.DICOM_CHARSET_ESCAPE_UNDECLARED, position, { tag, vr });
|
|
12362
|
+
}
|
|
12363
|
+
function charsetBytesUndecodable(position, tag, vr) {
|
|
12364
|
+
return build(WARNING_CODES.DICOM_CHARSET_BYTES_UNDECODABLE, position, { tag, vr });
|
|
12365
|
+
}
|
|
12366
|
+
function charsetExtensionNotReset(position, tag, vr) {
|
|
12367
|
+
return build(WARNING_CODES.DICOM_CHARSET_EXTENSION_NOT_RESET, position, { tag, vr });
|
|
12368
|
+
}
|
|
12369
|
+
|
|
12370
|
+
// src/parser/directory.ts
|
|
12371
|
+
function emitDirectoryFindings(source, frame, emit) {
|
|
12372
|
+
const analysis = analyzeDirectory(source);
|
|
12373
|
+
if (analysis === void 0) return;
|
|
12374
|
+
const deflated = isDeflated(source.fileMeta);
|
|
12375
|
+
const positionOf = (finding) => {
|
|
12376
|
+
if (deflated) return { byteOffset: frame.fileMetaEnd };
|
|
12377
|
+
if (finding.item === void 0) return { byteOffset: finding.element.byteOffset };
|
|
12378
|
+
const byteOffset = (finding.item.fileOffset ?? frame.origin) - frame.origin;
|
|
12379
|
+
const contextPath = [
|
|
12380
|
+
DIRECTORY_TAGS.RECORD_SEQUENCE,
|
|
12381
|
+
String(finding.item.index),
|
|
12382
|
+
finding.element.tag
|
|
12383
|
+
];
|
|
12384
|
+
return { byteOffset, contextPath };
|
|
12385
|
+
};
|
|
12386
|
+
for (const finding of analysis.findings) {
|
|
12387
|
+
const position = positionOf(finding);
|
|
12388
|
+
switch (finding.kind) {
|
|
12389
|
+
case "unresolved":
|
|
12390
|
+
emit(directoryOffsetUnresolved(position));
|
|
12391
|
+
break;
|
|
12392
|
+
case "malformed":
|
|
12393
|
+
emit(directoryOffsetMalformed(position));
|
|
12394
|
+
break;
|
|
12395
|
+
case "revisited":
|
|
12396
|
+
emit(directoryRecordRevisited(position));
|
|
12397
|
+
break;
|
|
12398
|
+
case "deflated":
|
|
12399
|
+
emit(directoryOffsetDeflated(position));
|
|
12400
|
+
break;
|
|
12401
|
+
}
|
|
12402
|
+
}
|
|
12403
|
+
}
|
|
12404
|
+
|
|
12405
|
+
// src/parser/errors.ts
|
|
12406
|
+
var FATAL_CODES = {
|
|
12407
|
+
NOT_DICOM_PART_10: "NOT_DICOM_PART_10",
|
|
12408
|
+
INVALID_FILE_META: "INVALID_FILE_META",
|
|
12409
|
+
UNSUPPORTED_TRANSFER_SYNTAX: "UNSUPPORTED_TRANSFER_SYNTAX",
|
|
12410
|
+
EMPTY_INPUT: "EMPTY_INPUT"
|
|
12411
|
+
};
|
|
12412
|
+
var OFFSET_FRAMES = {
|
|
12413
|
+
/**
|
|
12414
|
+
* Byte 0 is byte 0 of the buffer handed to `parseDicom`. The only frame in
|
|
12415
|
+
* which indexing the caller's own input by `byteOffset` is meaningful.
|
|
12416
|
+
*/
|
|
12417
|
+
INPUT: "input",
|
|
12418
|
+
/**
|
|
12419
|
+
* Byte 0 is byte 0 of the inflated Data Set of a Deflated Explicit VR LE
|
|
12420
|
+
* object (`1.2.840.10008.1.2.1.99`). The compressed input holds no such
|
|
12421
|
+
* byte, so the offset does not index it at any scale.
|
|
12422
|
+
*/
|
|
12423
|
+
INFLATED_DATASET: "inflated-dataset",
|
|
12424
|
+
/**
|
|
12425
|
+
* Byte 0 is byte 0 of a slice this parser cut from inside a Value Field: a
|
|
12426
|
+
* defined-length Sequence Item's value, or an `SQ`/`UN` value handed to a
|
|
12427
|
+
* descent. **Where that slice begins is deliberately not published** - see
|
|
12428
|
+
* this table's own note.
|
|
12429
|
+
*/
|
|
12430
|
+
VALUE_SLICE: "value-slice"
|
|
12431
|
+
};
|
|
12432
|
+
function valueSliceFrame(enclosing, slice, start) {
|
|
12433
|
+
return enclosing.origin === void 0 ? { buffer: slice, name: OFFSET_FRAMES.VALUE_SLICE } : { buffer: slice, name: OFFSET_FRAMES.VALUE_SLICE, origin: enclosing.origin + start };
|
|
12434
|
+
}
|
|
12435
|
+
function fileOffsetIn(frame, offset) {
|
|
12436
|
+
return frame.origin === void 0 ? void 0 : frame.origin + offset;
|
|
12437
|
+
}
|
|
12438
|
+
var DicomParseError = class extends Error {
|
|
12439
|
+
code;
|
|
12440
|
+
byteOffset;
|
|
12441
|
+
/**
|
|
12442
|
+
* The coordinate system {@link DicomParseError.byteOffset} is counted in.
|
|
12443
|
+
* See {@link OFFSET_FRAMES}.
|
|
12444
|
+
*/
|
|
12445
|
+
offsetFrame;
|
|
12446
|
+
snippet;
|
|
12447
|
+
contextPath;
|
|
12448
|
+
/**
|
|
12449
|
+
* Construct a new `DicomParseError`. All fields except `contextPath` are
|
|
12450
|
+
* required so every thrower populates positional context - and
|
|
12451
|
+
* `offsetFrame` is required for the same reason `byteOffset` is, because an
|
|
12452
|
+
* offset whose frame is optional is an offset whose frame is usually
|
|
12453
|
+
* missing.
|
|
12454
|
+
*
|
|
12455
|
+
* @internal
|
|
12456
|
+
*/
|
|
12457
|
+
constructor(code, message, byteOffset, offsetFrame, snippet, contextPath) {
|
|
12458
|
+
const formatted = `[${code}] ${message} (offset=${String(byteOffset)} frame=${offsetFrame})` + (contextPath !== void 0 && contextPath.length > 0 ? ` \u2026 in ${contextPath.join("/")}` : "");
|
|
12459
|
+
super(formatted);
|
|
12460
|
+
this.name = "DicomParseError";
|
|
12461
|
+
this.code = code;
|
|
12462
|
+
this.byteOffset = byteOffset;
|
|
12463
|
+
this.offsetFrame = offsetFrame;
|
|
12464
|
+
this.snippet = snippet;
|
|
12465
|
+
this.contextPath = contextPath;
|
|
12466
|
+
}
|
|
12467
|
+
};
|
|
12468
|
+
function buildSnippet(buffer, offset) {
|
|
12469
|
+
if (offset < 0 || offset >= buffer.length) return "";
|
|
12470
|
+
const end = Math.min(offset + 16, buffer.length);
|
|
12471
|
+
const slice = buffer.subarray(offset, end);
|
|
12472
|
+
const parts = [];
|
|
12473
|
+
for (const b of slice) {
|
|
12474
|
+
parts.push(b.toString(16).padStart(2, "0"));
|
|
12475
|
+
}
|
|
12476
|
+
return parts.join(" ");
|
|
12477
|
+
}
|
|
12478
|
+
|
|
12479
|
+
// src/parser/emit.ts
|
|
12480
|
+
function makeEmitter(ctx) {
|
|
12481
|
+
const escalate = (w) => {
|
|
12482
|
+
throw new DicomParseError(
|
|
12483
|
+
// The cast is deliberate: the WarningCode union does not overlap FatalCode at the
|
|
12484
|
+
// type level, but at runtime the strict-thrown error carries the
|
|
12485
|
+
// warning code so consumers can narrow on err.code uniformly.
|
|
12486
|
+
w.code,
|
|
12487
|
+
w.message,
|
|
12488
|
+
w.position.byteOffset,
|
|
12489
|
+
// Both come off the SAME frame object, so an escalation cannot name one
|
|
12490
|
+
// frame and cut its bytes from another. `DicomParseWarning.position`
|
|
12491
|
+
// itself carries no frame - that is `PRE-EXISTING` and stated on
|
|
12492
|
+
// `DicomPosition`, not closed here.
|
|
12493
|
+
ctx.frame.name,
|
|
12494
|
+
buildSnippet(ctx.frame.buffer, w.position.byteOffset),
|
|
12495
|
+
w.position.contextPath
|
|
12496
|
+
);
|
|
12497
|
+
};
|
|
12498
|
+
return (w) => {
|
|
12499
|
+
if (ctx.strict) escalate(w);
|
|
12500
|
+
if (ctx.profile !== void 0) {
|
|
12501
|
+
if (ctx.profile.suppressions.has(w.code)) return;
|
|
12502
|
+
if (ctx.profile.escalations.has(w.code)) escalate(w);
|
|
12503
|
+
}
|
|
12504
|
+
ctx.warnings.push(w);
|
|
12505
|
+
if (ctx.onWarning !== void 0) {
|
|
12506
|
+
try {
|
|
12507
|
+
ctx.onWarning(w);
|
|
12508
|
+
} catch {
|
|
12509
|
+
}
|
|
12510
|
+
}
|
|
12511
|
+
};
|
|
12512
|
+
}
|
|
12513
|
+
|
|
12514
|
+
// src/dictionary/generated/encapsulated-transfer-syntaxes.ts
|
|
12515
|
+
var ENCAPSULATED_TRANSFER_SYNTAX_EDITION = "2026c";
|
|
12516
|
+
var ENCAPSULATED_TRANSFER_SYNTAX_UIDS = Object.freeze([
|
|
12517
|
+
"1.2.840.10008.1.2.1.98",
|
|
12518
|
+
// Encapsulated Uncompressed Explicit VR Little Endian
|
|
12519
|
+
"1.2.840.10008.1.2.4.100",
|
|
12520
|
+
// MPEG2 Main Profile / Main Level
|
|
12521
|
+
"1.2.840.10008.1.2.4.100.1",
|
|
12522
|
+
// Fragmentable MPEG2 Main Profile / Main Level
|
|
12523
|
+
"1.2.840.10008.1.2.4.101",
|
|
12524
|
+
// MPEG2 Main Profile / High Level
|
|
12525
|
+
"1.2.840.10008.1.2.4.101.1",
|
|
12526
|
+
// Fragmentable MPEG2 Main Profile / High Level
|
|
12527
|
+
"1.2.840.10008.1.2.4.102",
|
|
12528
|
+
// MPEG-4 AVC/H.264 High Profile / Level 4.1
|
|
12529
|
+
"1.2.840.10008.1.2.4.102.1",
|
|
12530
|
+
// Fragmentable MPEG-4 AVC/H.264 High Profile / Level 4.1
|
|
12531
|
+
"1.2.840.10008.1.2.4.103",
|
|
12532
|
+
// MPEG-4 AVC/H.264 BD-compatible High Profile / Level 4.1
|
|
12533
|
+
"1.2.840.10008.1.2.4.103.1",
|
|
12534
|
+
// Fragmentable MPEG-4 AVC/H.264 BD-compatible High Profile / Level 4.1
|
|
12535
|
+
"1.2.840.10008.1.2.4.104",
|
|
12536
|
+
// MPEG-4 AVC/H.264 High Profile / Level 4.2 For 2D Video
|
|
12537
|
+
"1.2.840.10008.1.2.4.104.1",
|
|
12538
|
+
// Fragmentable MPEG-4 AVC/H.264 High Profile / Level 4.2 For 2D Video
|
|
12539
|
+
"1.2.840.10008.1.2.4.105",
|
|
12540
|
+
// MPEG-4 AVC/H.264 High Profile / Level 4.2 For 3D Video
|
|
12541
|
+
"1.2.840.10008.1.2.4.105.1",
|
|
12542
|
+
// Fragmentable MPEG-4 AVC/H.264 High Profile / Level 4.2 For 3D Video
|
|
12543
|
+
"1.2.840.10008.1.2.4.106",
|
|
12544
|
+
// MPEG-4 AVC/H.264 Stereo High Profile / Level 4.2
|
|
12545
|
+
"1.2.840.10008.1.2.4.106.1",
|
|
12546
|
+
// Fragmentable MPEG-4 AVC/H.264 Stereo High Profile / Level 4.2
|
|
12547
|
+
"1.2.840.10008.1.2.4.107",
|
|
12548
|
+
// HEVC/H.265 Main Profile / Level 5.1
|
|
12549
|
+
"1.2.840.10008.1.2.4.108",
|
|
12550
|
+
// HEVC/H.265 Main 10 Profile / Level 5.1
|
|
12551
|
+
"1.2.840.10008.1.2.4.110",
|
|
12552
|
+
// JPEG XL Lossless
|
|
12553
|
+
"1.2.840.10008.1.2.4.111",
|
|
12554
|
+
// JPEG XL JPEG Recompression
|
|
12555
|
+
"1.2.840.10008.1.2.4.112",
|
|
12556
|
+
// JPEG XL
|
|
12557
|
+
"1.2.840.10008.1.2.4.201",
|
|
12558
|
+
// High-Throughput JPEG 2000 Image Compression (Lossless Only)
|
|
12559
|
+
"1.2.840.10008.1.2.4.202",
|
|
12560
|
+
// High-Throughput JPEG 2000 with RPCL Options Image Compression (Lossless Only)
|
|
12561
|
+
"1.2.840.10008.1.2.4.203",
|
|
12562
|
+
// High-Throughput JPEG 2000 Image Compression
|
|
12563
|
+
"1.2.840.10008.1.2.4.50",
|
|
12564
|
+
// JPEG Baseline (Process 1)
|
|
12565
|
+
"1.2.840.10008.1.2.4.51",
|
|
12566
|
+
// JPEG Extended (Process 2 & 4)
|
|
12567
|
+
"1.2.840.10008.1.2.4.57",
|
|
12568
|
+
// JPEG Lossless, Non-Hierarchical (Process 14)
|
|
12569
|
+
"1.2.840.10008.1.2.4.70",
|
|
12570
|
+
// JPEG Lossless, Non-Hierarchical, First-Order Prediction (Process 14 [Selection Value 1])
|
|
12571
|
+
"1.2.840.10008.1.2.4.80",
|
|
12572
|
+
// JPEG-LS Lossless Image Compression
|
|
12573
|
+
"1.2.840.10008.1.2.4.81",
|
|
12574
|
+
// JPEG-LS Lossy (Near-Lossless) Image Compression
|
|
12575
|
+
"1.2.840.10008.1.2.4.90",
|
|
12576
|
+
// JPEG 2000 Image Compression (Lossless Only)
|
|
12577
|
+
"1.2.840.10008.1.2.4.91",
|
|
12578
|
+
// JPEG 2000 Image Compression
|
|
12579
|
+
"1.2.840.10008.1.2.4.92",
|
|
12580
|
+
// JPEG 2000 Part 2 Multi-component Image Compression (Lossless Only)
|
|
12581
|
+
"1.2.840.10008.1.2.4.93",
|
|
12582
|
+
// JPEG 2000 Part 2 Multi-component Image Compression
|
|
12583
|
+
"1.2.840.10008.1.2.5",
|
|
12584
|
+
// RLE Lossless
|
|
12585
|
+
"1.2.840.10008.1.2.8.1"
|
|
12586
|
+
// Deflated Image Frame Compression
|
|
12587
|
+
]);
|
|
12588
|
+
|
|
12589
|
+
// src/parser/fatals.ts
|
|
12590
|
+
var NATIVE_TRANSFER_SYNTAXES = Object.freeze([
|
|
12591
|
+
"1.2.840.10008.1.2",
|
|
12592
|
+
"1.2.840.10008.1.2.1",
|
|
12593
|
+
"1.2.840.10008.1.2.2",
|
|
12594
|
+
"1.2.840.10008.1.2.1.99"
|
|
12595
|
+
]);
|
|
12596
|
+
var SUPPORTED_TRANSFER_SYNTAXES = `${NATIVE_TRANSFER_SYNTAXES.join(", ")}, every encapsulated Pixel Data Transfer Syntax PS3.5 ${ENCAPSULATED_TRANSFER_SYNTAX_EDITION} section A.4 names, and the four JPIP Referenced Transfer Syntaxes of its sections A.6, A.7, A.11 and A.12`;
|
|
12597
|
+
var ZLIB_CODES = Object.freeze(
|
|
12598
|
+
/* @__PURE__ */ new Set([
|
|
12599
|
+
"Z_OK",
|
|
12600
|
+
"Z_STREAM_END",
|
|
12601
|
+
"Z_NEED_DICT",
|
|
12602
|
+
"Z_ERRNO",
|
|
12603
|
+
"Z_STREAM_ERROR",
|
|
12604
|
+
"Z_DATA_ERROR",
|
|
12605
|
+
"Z_MEM_ERROR",
|
|
12606
|
+
"Z_BUF_ERROR",
|
|
12607
|
+
"Z_VERSION_ERROR"
|
|
12608
|
+
])
|
|
12609
|
+
);
|
|
12610
|
+
var FATAL_MESSAGES = Object.freeze({
|
|
12611
|
+
EMPTY_INPUT: {
|
|
12612
|
+
code: FATAL_CODES.EMPTY_INPUT,
|
|
12613
|
+
message: "Input is empty."
|
|
12614
|
+
},
|
|
12615
|
+
EMPTY_INPUT_AFTER_NORMALIZATION: {
|
|
12616
|
+
code: FATAL_CODES.EMPTY_INPUT,
|
|
12617
|
+
message: "Input is empty after normalization."
|
|
12618
|
+
},
|
|
12619
|
+
NOT_DICOM_PART_10_REQUIRED: {
|
|
12620
|
+
code: FATAL_CODES.NOT_DICOM_PART_10,
|
|
12621
|
+
message: "Missing DICM magic at offset 128 (stripPreamble='require')."
|
|
12622
|
+
},
|
|
12623
|
+
NOT_DICOM_PART_10: {
|
|
12624
|
+
code: FATAL_CODES.NOT_DICOM_PART_10,
|
|
12625
|
+
message: "Input is not a DICOM Part 10 file (no DICM magic at offset 128 and no recognizable File Meta group at offset 0)."
|
|
12626
|
+
},
|
|
12627
|
+
// `{ts}` is NOT the UID. It is the PS3.6 registry's own name for the UID, or a
|
|
12628
|
+
// fixed phrase when PS3.6 does not publish one - see `renderTransferSyntax`.
|
|
12629
|
+
UNSUPPORTED_TRANSFER_SYNTAX: {
|
|
12630
|
+
code: FATAL_CODES.UNSUPPORTED_TRANSFER_SYNTAX,
|
|
12631
|
+
message: `{ts} in (0002,0010) is not supported by @cosyte/dicom v1 (supported: ${SUPPORTED_TRANSFER_SYNTAXES}).`
|
|
12632
|
+
},
|
|
12633
|
+
FILE_META_TRUNCATED: {
|
|
12634
|
+
code: FATAL_CODES.INVALID_FILE_META,
|
|
12635
|
+
message: "File Meta is truncated."
|
|
12636
|
+
},
|
|
12637
|
+
// The declared group length is deliberately absent. It is four bytes of the
|
|
12638
|
+
// document read as a 32-bit integer. **NOT because this code fires only when
|
|
12639
|
+
// those four bytes are fabricated** - an honestly truncated file raises it
|
|
12640
|
+
// with a perfectly correct group length, measured - but because they are four
|
|
12641
|
+
// bytes a sender wrote in either reading, and in the other one they are part
|
|
12642
|
+
// of somebody's value.
|
|
12643
|
+
FILE_META_GROUP_LENGTH_OVERRUNS: {
|
|
12644
|
+
code: FATAL_CODES.INVALID_FILE_META,
|
|
12645
|
+
message: "(0002,0000) FileMetaInformationGroupLength declares more bytes than remain in the input. The declared length and the count of bytes that remain are withheld; the byte offset locates the group."
|
|
12646
|
+
},
|
|
12647
|
+
FILE_META_TRANSFER_SYNTAX_MISSING: {
|
|
12648
|
+
code: FATAL_CODES.INVALID_FILE_META,
|
|
12649
|
+
message: "Required File Meta element (0002,0010) Transfer Syntax UID is missing or not UI."
|
|
12650
|
+
},
|
|
12651
|
+
TRUNCATED_DATASET_HEADER: {
|
|
12652
|
+
code: FATAL_CODES.INVALID_FILE_META,
|
|
12653
|
+
message: "Truncated dataset (header read past buffer end)."
|
|
12654
|
+
},
|
|
12655
|
+
TRUNCATED_FFFE_HEADER: {
|
|
12656
|
+
code: FATAL_CODES.INVALID_FILE_META,
|
|
12657
|
+
message: "Truncated dataset (FFFE header read past buffer end)."
|
|
12658
|
+
},
|
|
12659
|
+
TRUNCATED_EXPLICIT_VR_HEADER: {
|
|
12660
|
+
code: FATAL_CODES.INVALID_FILE_META,
|
|
12661
|
+
message: "Truncated dataset (Explicit VR header read past buffer end)."
|
|
12662
|
+
},
|
|
12663
|
+
SQ_ITEM_HEADER_TRUNCATED: {
|
|
12664
|
+
code: FATAL_CODES.INVALID_FILE_META,
|
|
12665
|
+
message: "Truncated dataset (SQ item header read past buffer end)."
|
|
12666
|
+
},
|
|
12667
|
+
// Neither the marker's element number nor its length field is here. Both are
|
|
12668
|
+
// read at a position the reader may have desynchronized to, so both are
|
|
12669
|
+
// document content: the length field measured as 1109414477, `"MR B"`.
|
|
12670
|
+
UNEXPECTED_FFFE_AT_DATASET_LEVEL: {
|
|
12671
|
+
code: FATAL_CODES.INVALID_FILE_META,
|
|
12672
|
+
message: "An (FFFE,xxxx) delimitation item appears at Data Set level under Explicit VR, where no sequence is open. Its element number and its length field are withheld; the byte offset locates it."
|
|
12673
|
+
},
|
|
12674
|
+
UNEXPECTED_FFFE_AT_DATASET_ROOT: {
|
|
12675
|
+
code: FATAL_CODES.INVALID_FILE_META,
|
|
12676
|
+
message: "An (FFFE,xxxx) delimitation item appears at Data Set level under Implicit VR LE, where no sequence is open. Its element number is withheld; the byte offset locates it."
|
|
12677
|
+
},
|
|
12678
|
+
UNDEFINED_LENGTH_ON_NON_SQ_EXPLICIT: {
|
|
12679
|
+
code: FATAL_CODES.INVALID_FILE_META,
|
|
12680
|
+
message: "An element with VR={vr} declares undefined length (0xFFFFFFFF) under Explicit VR. PS3.5 2026c permits that for a Sequence (7.5.2 Delimitation of The Sequence of Items), for encapsulated (7FE0,0010) Pixel Data (A.4), and for the UN form CP-246 addresses (6.2.2 Unknown (UN) Value Representation), and this element is none of them. Its tag is withheld; the byte offset locates it."
|
|
12681
|
+
},
|
|
12682
|
+
UNDEFINED_LENGTH_ON_NON_SQ_IMPLICIT: {
|
|
12683
|
+
code: FATAL_CODES.INVALID_FILE_META,
|
|
12684
|
+
message: "An element whose VR resolved to {vr} declares undefined length (0xFFFFFFFF) under Implicit VR LE, and the descent as an Implicit VR LE item stream (PS3.5 2026c 6.2.2, the UN form CP-246 addresses) did not succeed. Its tag is withheld; the byte offset locates it."
|
|
12685
|
+
},
|
|
12686
|
+
ELEMENT_LENGTH_EXCEEDS_BUFFER: {
|
|
12687
|
+
code: FATAL_CODES.INVALID_FILE_META,
|
|
12688
|
+
message: "An element declares a Value Length reaching past the end of the bytes being read. Its tag, its declared length and the count of bytes that remain are withheld; the byte offset locates it."
|
|
12689
|
+
},
|
|
12690
|
+
UNEXPECTED_TAG_INSIDE_SEQUENCE: {
|
|
12691
|
+
code: FATAL_CODES.INVALID_FILE_META,
|
|
12692
|
+
message: "A sequence's item stream holds a tag that is neither (FFFE,E000) Item nor (FFFE,E0DD) Sequence Delimitation Item (PS3.5 7.5). That tag is withheld: a value being read as an item stream makes its four bytes document content. The byte offset locates it."
|
|
12693
|
+
},
|
|
12694
|
+
ENCAPSULATED_FRAGMENT_EXCEEDS_BUFFER: {
|
|
12695
|
+
code: FATAL_CODES.INVALID_FILE_META,
|
|
12696
|
+
message: "An encapsulated Pixel Data fragment declares a length reaching past the end of the bytes being read. The declared length is withheld; the byte offset locates the fragment."
|
|
12697
|
+
},
|
|
12698
|
+
ITEM_LENGTH_EXCEEDS_BUFFER: {
|
|
12699
|
+
code: FATAL_CODES.INVALID_FILE_META,
|
|
12700
|
+
message: "An (FFFE,E000) Item declares a length reaching past the end of the bytes being read. The declared length is withheld; the byte offset locates the item."
|
|
12701
|
+
},
|
|
12702
|
+
SQ_NESTING_DEPTH_EXCEEDED: {
|
|
12703
|
+
code: FATAL_CODES.INVALID_FILE_META,
|
|
12704
|
+
message: "SQ nesting depth exceeds {n}."
|
|
12705
|
+
},
|
|
12706
|
+
INFLATED_PAYLOAD_EXCEEDS_CAP: {
|
|
12707
|
+
code: FATAL_CODES.INVALID_FILE_META,
|
|
12708
|
+
message: "Inflated Deflated TS payload exceeds {n}-byte cap."
|
|
12709
|
+
},
|
|
12710
|
+
// `{zlib}` is a member of the nine-name `zlib.codes` table or nothing. zlib's
|
|
12711
|
+
// own `err.message` is never forwarded: it is a string from a library handed
|
|
12712
|
+
// the sender's bytes, which is the one shape of third-party text this parser
|
|
12713
|
+
// cannot vouch for.
|
|
12714
|
+
INFLATE_FAILED: {
|
|
12715
|
+
code: FATAL_CODES.INVALID_FILE_META,
|
|
12716
|
+
message: "Failed to inflate Deflated TS payload (zlib error code: {zlib})."
|
|
12717
|
+
}
|
|
12718
|
+
});
|
|
12719
|
+
function renderTransferSyntax(ts) {
|
|
12720
|
+
if (ts === void 0) return "The Transfer Syntax UID";
|
|
12721
|
+
const name = uid(ts)?.name ?? "";
|
|
12722
|
+
return name.length > 0 ? `Transfer Syntax ${name}` : "The Transfer Syntax UID";
|
|
12723
|
+
}
|
|
12724
|
+
function renderZlibCode(code) {
|
|
12725
|
+
return code !== void 0 && ZLIB_CODES.has(code) ? code : WITHHELD;
|
|
12726
|
+
}
|
|
12727
|
+
function build2(key, byteOffset, offsetFrame, snippet, tokens = {}) {
|
|
12728
|
+
const entry = FATAL_MESSAGES[key];
|
|
12729
|
+
const message = entry.message.replace("{vr}", renderVr(tokens.vr)).replace("{ts}", renderTransferSyntax(tokens.ts)).replace("{zlib}", renderZlibCode(tokens.zlib)).replace("{n}", String(tokens.n ?? 0));
|
|
12730
|
+
return new DicomParseError(entry.code, message, byteOffset, offsetFrame, snippet);
|
|
12731
|
+
}
|
|
12732
|
+
function at(key, frame, offset, tokens = {}) {
|
|
12733
|
+
return build2(key, offset, frame.name, buildSnippet(frame.buffer, offset), tokens);
|
|
12734
|
+
}
|
|
12735
|
+
function emptyInput() {
|
|
12736
|
+
return build2("EMPTY_INPUT", 0, OFFSET_FRAMES.INPUT, "");
|
|
12737
|
+
}
|
|
12738
|
+
function emptyInputAfterNormalization() {
|
|
12739
|
+
return build2("EMPTY_INPUT_AFTER_NORMALIZATION", 0, OFFSET_FRAMES.INPUT, "");
|
|
12740
|
+
}
|
|
12741
|
+
function notDicomPart10Required(frame, offset) {
|
|
12742
|
+
return at("NOT_DICOM_PART_10_REQUIRED", frame, offset);
|
|
12743
|
+
}
|
|
12744
|
+
function notDicomPart10(frame, offset) {
|
|
12745
|
+
return at("NOT_DICOM_PART_10", frame, offset);
|
|
12746
|
+
}
|
|
12747
|
+
function unsupportedTransferSyntax(frame, offset, ts) {
|
|
12748
|
+
const name = uid(ts)?.name ?? "";
|
|
12749
|
+
return build2(
|
|
12750
|
+
"UNSUPPORTED_TRANSFER_SYNTAX",
|
|
12751
|
+
offset,
|
|
12752
|
+
frame.name,
|
|
12753
|
+
name.length > 0 ? name : buildSnippet(frame.buffer, offset),
|
|
12754
|
+
{ ts }
|
|
12755
|
+
);
|
|
12756
|
+
}
|
|
12757
|
+
function fileMetaTruncated(frame, offset) {
|
|
12758
|
+
return at("FILE_META_TRUNCATED", frame, offset);
|
|
12759
|
+
}
|
|
12760
|
+
function fileMetaGroupLengthOverruns(frame, offset) {
|
|
12761
|
+
return at("FILE_META_GROUP_LENGTH_OVERRUNS", frame, offset);
|
|
12762
|
+
}
|
|
12763
|
+
function fileMetaTransferSyntaxMissing(frame, offset) {
|
|
12764
|
+
return at("FILE_META_TRANSFER_SYNTAX_MISSING", frame, offset);
|
|
12765
|
+
}
|
|
12766
|
+
function truncatedDatasetHeader(frame, offset) {
|
|
12767
|
+
return at("TRUNCATED_DATASET_HEADER", frame, offset);
|
|
12768
|
+
}
|
|
12769
|
+
function truncatedFffeHeader(frame, offset) {
|
|
12770
|
+
return at("TRUNCATED_FFFE_HEADER", frame, offset);
|
|
12771
|
+
}
|
|
12772
|
+
function truncatedExplicitVrHeader(frame, offset) {
|
|
12773
|
+
return at("TRUNCATED_EXPLICIT_VR_HEADER", frame, offset);
|
|
12774
|
+
}
|
|
12775
|
+
function sqItemHeaderTruncated(frame, offset) {
|
|
12776
|
+
return at("SQ_ITEM_HEADER_TRUNCATED", frame, offset);
|
|
12777
|
+
}
|
|
12778
|
+
function unexpectedFffeAtDatasetLevel(frame, offset) {
|
|
12779
|
+
return at("UNEXPECTED_FFFE_AT_DATASET_LEVEL", frame, offset);
|
|
12780
|
+
}
|
|
12781
|
+
function unexpectedFffeAtDatasetRoot(frame, offset) {
|
|
12782
|
+
return at("UNEXPECTED_FFFE_AT_DATASET_ROOT", frame, offset);
|
|
12783
|
+
}
|
|
12784
|
+
function undefinedLengthOnNonSqExplicit(frame, offset, vr) {
|
|
12785
|
+
return at("UNDEFINED_LENGTH_ON_NON_SQ_EXPLICIT", frame, offset, { vr });
|
|
12786
|
+
}
|
|
12787
|
+
function undefinedLengthOnNonSqImplicit(frame, offset, vr) {
|
|
12788
|
+
return at("UNDEFINED_LENGTH_ON_NON_SQ_IMPLICIT", frame, offset, { vr });
|
|
12789
|
+
}
|
|
12790
|
+
function elementLengthExceedsBuffer(frame, offset) {
|
|
12791
|
+
return at("ELEMENT_LENGTH_EXCEEDS_BUFFER", frame, offset);
|
|
12792
|
+
}
|
|
12793
|
+
function unexpectedTagInsideSequence(frame, offset) {
|
|
12794
|
+
return at("UNEXPECTED_TAG_INSIDE_SEQUENCE", frame, offset);
|
|
12795
|
+
}
|
|
12796
|
+
function encapsulatedFragmentExceedsBuffer(frame, offset) {
|
|
12797
|
+
return at("ENCAPSULATED_FRAGMENT_EXCEEDS_BUFFER", frame, offset);
|
|
12798
|
+
}
|
|
12799
|
+
function itemLengthExceedsBuffer(frame, offset) {
|
|
12800
|
+
return at("ITEM_LENGTH_EXCEEDS_BUFFER", frame, offset);
|
|
12801
|
+
}
|
|
12802
|
+
function sqNestingDepthExceeded(frame, offset, limit) {
|
|
12803
|
+
return at("SQ_NESTING_DEPTH_EXCEEDED", frame, offset, { n: limit });
|
|
12804
|
+
}
|
|
12805
|
+
function inflatedPayloadExceedsCap(frame, offset, cap) {
|
|
12806
|
+
return at("INFLATED_PAYLOAD_EXCEEDS_CAP", frame, offset, { n: cap });
|
|
12807
|
+
}
|
|
12808
|
+
function inflateFailed(frame, offset, code) {
|
|
12809
|
+
return at("INFLATE_FAILED", frame, offset, ...code !== void 0 ? [{ zlib: code }] : []);
|
|
12810
|
+
}
|
|
12811
|
+
function copyValueBytes(src) {
|
|
12812
|
+
const out = Buffer.allocUnsafeSlow(src.length);
|
|
12813
|
+
src.copy(out);
|
|
12814
|
+
return out;
|
|
12815
|
+
}
|
|
12816
|
+
var ByteCursor = class {
|
|
12817
|
+
buffer;
|
|
12818
|
+
littleEndian;
|
|
12819
|
+
position;
|
|
12820
|
+
/**
|
|
12821
|
+
* Construct a new cursor at `position` (default 0) over `buffer` with
|
|
12822
|
+
* the given endian orientation.
|
|
12823
|
+
*
|
|
12824
|
+
* @internal
|
|
12825
|
+
*/
|
|
12826
|
+
constructor(buffer, littleEndian, position = 0) {
|
|
12827
|
+
this.buffer = buffer;
|
|
12828
|
+
this.littleEndian = littleEndian;
|
|
12829
|
+
this.position = position;
|
|
12830
|
+
}
|
|
12831
|
+
/** Read a 16-bit unsigned integer at the current position; advance by 2. */
|
|
12832
|
+
readUInt16() {
|
|
12833
|
+
if (this.position + 2 > this.buffer.length) {
|
|
12834
|
+
throw new RangeError("ByteCursor: read past end of buffer");
|
|
12835
|
+
}
|
|
12836
|
+
const v = this.littleEndian ? this.buffer.readUInt16LE(this.position) : this.buffer.readUInt16BE(this.position);
|
|
12837
|
+
this.position += 2;
|
|
12838
|
+
return v;
|
|
12839
|
+
}
|
|
12840
|
+
/** Read a 32-bit unsigned integer at the current position; advance by 4. */
|
|
12841
|
+
readUInt32() {
|
|
12842
|
+
if (this.position + 4 > this.buffer.length) {
|
|
12843
|
+
throw new RangeError("ByteCursor: read past end of buffer");
|
|
12844
|
+
}
|
|
12845
|
+
const v = this.littleEndian ? this.buffer.readUInt32LE(this.position) : this.buffer.readUInt32BE(this.position);
|
|
12846
|
+
this.position += 4;
|
|
12847
|
+
return v;
|
|
12848
|
+
}
|
|
12849
|
+
/** Read a 16-bit unsigned integer at an explicit offset; cursor unchanged. */
|
|
12850
|
+
readUInt16At(offset) {
|
|
12851
|
+
if (offset < 0 || offset + 2 > this.buffer.length) {
|
|
12852
|
+
throw new RangeError("ByteCursor: read past end of buffer");
|
|
12853
|
+
}
|
|
12854
|
+
return this.littleEndian ? this.buffer.readUInt16LE(offset) : this.buffer.readUInt16BE(offset);
|
|
12855
|
+
}
|
|
12856
|
+
/** Read a 32-bit unsigned integer at an explicit offset; cursor unchanged. */
|
|
12857
|
+
readUInt32At(offset) {
|
|
12858
|
+
if (offset < 0 || offset + 4 > this.buffer.length) {
|
|
12859
|
+
throw new RangeError("ByteCursor: read past end of buffer");
|
|
12860
|
+
}
|
|
12861
|
+
return this.littleEndian ? this.buffer.readUInt32LE(offset) : this.buffer.readUInt32BE(offset);
|
|
12862
|
+
}
|
|
12863
|
+
/**
|
|
12864
|
+
* Take a `length`-byte view starting at the current position; advance
|
|
12865
|
+
* the cursor by `length`. Returns a `Buffer.subarray` (zero-copy view);
|
|
12866
|
+
* callers wanting a copy must `Buffer.from(slice)` themselves.
|
|
12867
|
+
*/
|
|
12868
|
+
slice(length) {
|
|
12869
|
+
if (length < 0 || this.position + length > this.buffer.length) {
|
|
12870
|
+
throw new RangeError("ByteCursor: read past end of buffer");
|
|
12871
|
+
}
|
|
12872
|
+
const out = this.buffer.subarray(this.position, this.position + length);
|
|
12873
|
+
this.position += length;
|
|
12874
|
+
return out;
|
|
12875
|
+
}
|
|
12876
|
+
/** Bytes remaining between the current position and the end of the buffer. */
|
|
12877
|
+
remaining() {
|
|
12878
|
+
return this.buffer.length - this.position;
|
|
12879
|
+
}
|
|
12880
|
+
};
|
|
12881
|
+
|
|
12882
|
+
// src/dataset/vr/iso2022.ts
|
|
12883
|
+
var ESC = 27;
|
|
12884
|
+
var LF = 10;
|
|
12885
|
+
var FF = 12;
|
|
12886
|
+
var CR = 13;
|
|
12887
|
+
var SPACE = 32;
|
|
12888
|
+
var DEL = 127;
|
|
12889
|
+
var BACKSLASH = 92;
|
|
12890
|
+
var CARET = 94;
|
|
12891
|
+
var EQUALS = 61;
|
|
12892
|
+
var REPLACEMENT = String.fromCharCode(65533);
|
|
12893
|
+
var NO_CODE_EXTENSION_VALUE_1 = /* @__PURE__ */ new Set(["ISO_IR 192", "GB18030", "GBK"]);
|
|
12894
|
+
var ESCAPE_SEQUENCES = [
|
|
12895
|
+
{ tail: [40, 66], ir: 6, element: "G0" },
|
|
12896
|
+
{ tail: [45, 65], ir: 100, element: "G1" },
|
|
12897
|
+
{ tail: [45, 66], ir: 101, element: "G1" },
|
|
12898
|
+
{ tail: [45, 67], ir: 109, element: "G1" },
|
|
12899
|
+
{ tail: [45, 68], ir: 110, element: "G1" },
|
|
12900
|
+
{ tail: [45, 76], ir: 144, element: "G1" },
|
|
12901
|
+
{ tail: [45, 71], ir: 127, element: "G1" },
|
|
12902
|
+
{ tail: [45, 70], ir: 126, element: "G1" },
|
|
12903
|
+
{ tail: [45, 72], ir: 138, element: "G1" },
|
|
12904
|
+
{ tail: [45, 77], ir: 148, element: "G1" },
|
|
12905
|
+
{ tail: [45, 98], ir: 203, element: "G1" },
|
|
12906
|
+
{ tail: [45, 84], ir: 166, element: "G1" },
|
|
12907
|
+
{ tail: [41, 73], ir: 13, element: "G1" },
|
|
12908
|
+
{ tail: [40, 74], ir: 14, element: "G0" },
|
|
12909
|
+
{ tail: [36, 66], ir: 87, element: "G0" },
|
|
12910
|
+
{ tail: [36, 40, 68], ir: 159, element: "G0" },
|
|
12911
|
+
{ tail: [36, 41, 67], ir: 149, element: "G1" },
|
|
12912
|
+
{ tail: [36, 41, 65], ir: 58, element: "G1" }
|
|
12913
|
+
];
|
|
12914
|
+
var SINGLE_BYTE_G1_ROWS = [
|
|
12915
|
+
100,
|
|
12916
|
+
101,
|
|
12917
|
+
109,
|
|
12918
|
+
110,
|
|
12919
|
+
144,
|
|
12920
|
+
127,
|
|
12921
|
+
126,
|
|
12922
|
+
138,
|
|
12923
|
+
148,
|
|
12924
|
+
203,
|
|
12925
|
+
166
|
|
12926
|
+
];
|
|
12927
|
+
var TERM_ROWS = (() => {
|
|
12928
|
+
const rows = /* @__PURE__ */ new Map();
|
|
12929
|
+
const addBoth = (ir, row2) => {
|
|
12930
|
+
rows.set(`ISO 2022 IR ${String(ir)}`, row2);
|
|
12931
|
+
rows.set(`ISO_IR ${String(ir)}`, row2);
|
|
12932
|
+
};
|
|
12933
|
+
addBoth(6, { declares: [6], initial: { g0: 6, g1: void 0 } });
|
|
12934
|
+
for (const ir of SINGLE_BYTE_G1_ROWS) {
|
|
12935
|
+
addBoth(ir, { declares: [6, ir], initial: { g0: 6, g1: ir } });
|
|
12936
|
+
}
|
|
12937
|
+
addBoth(13, { declares: [14, 13], initial: { g0: 14, g1: 13 } });
|
|
12938
|
+
for (const ir of [87, 159, 149, 58]) rows.set(`ISO 2022 IR ${String(ir)}`, { declares: [ir] });
|
|
12939
|
+
return rows;
|
|
12940
|
+
})();
|
|
12941
|
+
var SINGLE_BYTE_LABELS = /* @__PURE__ */ new Map([
|
|
12942
|
+
[100, "latin1"],
|
|
12943
|
+
[101, "iso-8859-2"],
|
|
12944
|
+
[109, "iso-8859-3"],
|
|
12945
|
+
[110, "iso-8859-4"],
|
|
12946
|
+
[144, "iso-8859-5"],
|
|
12947
|
+
[127, "iso-8859-6"],
|
|
12948
|
+
[126, "iso-8859-7"],
|
|
12949
|
+
[138, "iso-8859-8"],
|
|
12950
|
+
[148, "iso-8859-9"],
|
|
12951
|
+
[203, "iso-8859-15"],
|
|
12952
|
+
[166, "windows-874"],
|
|
12953
|
+
[13, "shift_jis"]
|
|
12954
|
+
]);
|
|
12955
|
+
var NINETY_FOUR_CHARACTER_G1 = /* @__PURE__ */ new Set([13]);
|
|
12956
|
+
function gb2312Assigned(row2, cell) {
|
|
12957
|
+
if (row2 === 2) {
|
|
12958
|
+
return cell >= 17 && cell <= 66 || cell >= 69 && cell <= 78 || cell >= 81 && cell <= 92;
|
|
12959
|
+
}
|
|
12960
|
+
if (row2 === 6) return cell >= 1 && cell <= 24 || cell >= 33 && cell <= 56;
|
|
12961
|
+
if (row2 === 8) return cell >= 1 && cell <= 26 || cell >= 37 && cell <= 73;
|
|
12962
|
+
return true;
|
|
12963
|
+
}
|
|
12964
|
+
var DOUBLE_BYTE_SETS = /* @__PURE__ */ new Map([
|
|
12965
|
+
[
|
|
12966
|
+
87,
|
|
12967
|
+
{
|
|
12968
|
+
label: "euc-jp",
|
|
12969
|
+
prefix: [],
|
|
12970
|
+
assigned: (row2) => row2 >= 1 && row2 <= 8 || row2 >= 16 && row2 <= 84
|
|
12971
|
+
}
|
|
12972
|
+
],
|
|
12973
|
+
[159, { label: "euc-jp", prefix: [143], assigned: (row2) => row2 <= 77 }],
|
|
12974
|
+
[149, { label: "euc-kr", prefix: [], assigned: () => true }],
|
|
12975
|
+
[58, { label: "gb18030", prefix: [], assigned: gb2312Assigned }]
|
|
12976
|
+
]);
|
|
12977
|
+
var decoders = /* @__PURE__ */ new Map();
|
|
12978
|
+
function decoderFor(label) {
|
|
12979
|
+
if (!decoders.has(label)) {
|
|
12980
|
+
let decoder;
|
|
12981
|
+
try {
|
|
12982
|
+
decoder = new TextDecoder(label, { fatal: false });
|
|
12983
|
+
} catch {
|
|
12984
|
+
decoder = void 0;
|
|
12985
|
+
}
|
|
12986
|
+
decoders.set(label, decoder);
|
|
12987
|
+
}
|
|
12988
|
+
return decoders.get(label);
|
|
12989
|
+
}
|
|
12990
|
+
function isCharacter(text) {
|
|
12991
|
+
const cp = text.codePointAt(0);
|
|
12992
|
+
if (cp === void 0 || String.fromCodePoint(cp).length !== text.length) return false;
|
|
12993
|
+
return cp >= 128 && cp !== 65533 && !(cp >= 57344 && cp <= 63743);
|
|
12994
|
+
}
|
|
12995
|
+
var singleByteTables = /* @__PURE__ */ new Map();
|
|
12996
|
+
function singleByteCharacter(ir, byte) {
|
|
12997
|
+
let table = singleByteTables.get(ir);
|
|
12998
|
+
if (table === void 0) {
|
|
12999
|
+
const label = SINGLE_BYTE_LABELS.get(ir);
|
|
13000
|
+
const decoder = label === void 0 ? void 0 : decoderFor(label);
|
|
13001
|
+
const built = [];
|
|
13002
|
+
for (let b = 160; b <= 255; b += 1) {
|
|
13003
|
+
const outside = NINETY_FOUR_CHARACTER_G1.has(ir) && (b === 160 || b === 255);
|
|
13004
|
+
const text = decoder === void 0 || outside ? "" : decoder.decode(Uint8Array.of(b));
|
|
13005
|
+
built.push(isCharacter(text) ? text : void 0);
|
|
13006
|
+
}
|
|
13007
|
+
table = built;
|
|
13008
|
+
singleByteTables.set(ir, table);
|
|
13009
|
+
}
|
|
13010
|
+
return table[byte - 160];
|
|
13011
|
+
}
|
|
13012
|
+
var pairCaches = /* @__PURE__ */ new Map();
|
|
13013
|
+
function pairCharacter(set, ir, first, second) {
|
|
13014
|
+
const row2 = (first & 127) - 32;
|
|
13015
|
+
const cell = (second & 127) - 32;
|
|
13016
|
+
if (!set.assigned(row2, cell)) return void 0;
|
|
13017
|
+
let cache = pairCaches.get(ir);
|
|
13018
|
+
if (cache === void 0) {
|
|
13019
|
+
cache = /* @__PURE__ */ new Map();
|
|
13020
|
+
pairCaches.set(ir, cache);
|
|
13021
|
+
}
|
|
13022
|
+
const key = row2 * 256 + cell;
|
|
13023
|
+
if (!cache.has(key)) {
|
|
13024
|
+
const decoder = decoderFor(set.label);
|
|
13025
|
+
const text = decoder === void 0 ? "" : decoder.decode(Uint8Array.of(...set.prefix, first | 128, second | 128));
|
|
13026
|
+
cache.set(key, isCharacter(text) ? text : void 0);
|
|
13027
|
+
}
|
|
13028
|
+
return cache.get(key);
|
|
13029
|
+
}
|
|
13030
|
+
function at2(bytes, index) {
|
|
13031
|
+
return bytes[index] ?? -1;
|
|
13032
|
+
}
|
|
13033
|
+
function matchEscape(bytes, index) {
|
|
13034
|
+
return ESCAPE_SEQUENCES.find(
|
|
13035
|
+
(sequence) => sequence.tail.every((byte, k) => at2(bytes, index + 1 + k) === byte)
|
|
13036
|
+
);
|
|
13037
|
+
}
|
|
13038
|
+
function isLineBreak(byte) {
|
|
13039
|
+
return byte === CR || byte === LF || byte === FF;
|
|
13040
|
+
}
|
|
13041
|
+
function endOfUnrecognizedRun(bytes, from) {
|
|
13042
|
+
let index = from;
|
|
13043
|
+
while (index < bytes.length) {
|
|
13044
|
+
const byte = at2(bytes, index);
|
|
13045
|
+
if (isLineBreak(byte) || byte === ESC && matchEscape(bytes, index) !== void 0) break;
|
|
13046
|
+
index += 1;
|
|
13047
|
+
}
|
|
13048
|
+
return index;
|
|
13049
|
+
}
|
|
13050
|
+
function isDelimiter(byte, delimiters) {
|
|
13051
|
+
if (delimiters === "personName") return byte === BACKSLASH || byte === CARET || byte === EQUALS;
|
|
13052
|
+
if (delimiters === "multiValued") return byte === BACKSLASH;
|
|
13053
|
+
return false;
|
|
13054
|
+
}
|
|
13055
|
+
function isGl(byte) {
|
|
13056
|
+
return byte >= 33 && byte <= 126;
|
|
13057
|
+
}
|
|
13058
|
+
function isGr94(byte) {
|
|
13059
|
+
return byte >= 161 && byte <= 254;
|
|
13060
|
+
}
|
|
13061
|
+
function usesCodeExtensions(terms) {
|
|
13062
|
+
return terms !== void 0 && terms.length > 1 && !NO_CODE_EXTENSION_VALUE_1.has(terms[0] ?? "");
|
|
13063
|
+
}
|
|
13064
|
+
function decodeWithCodeExtensions(bytes, terms, delimiters) {
|
|
13065
|
+
const declared = /* @__PURE__ */ new Set();
|
|
13066
|
+
for (const term of terms) for (const ir of TERM_ROWS.get(term)?.declares ?? []) declared.add(ir);
|
|
13067
|
+
if (terms[0] === "") declared.add(6);
|
|
13068
|
+
const initial = TERM_ROWS.get(terms[0] ?? "")?.initial ?? { g0: 6, g1: void 0 };
|
|
13069
|
+
let g0 = initial.g0;
|
|
13070
|
+
let g1 = initial.g1;
|
|
13071
|
+
let escapeUndeclared = false;
|
|
13072
|
+
let bytesUndecodable = false;
|
|
13073
|
+
let extensionNotReset = false;
|
|
13074
|
+
const out = [];
|
|
13075
|
+
const reset = () => {
|
|
13076
|
+
if (g0 !== initial.g0) extensionNotReset = true;
|
|
13077
|
+
g0 = initial.g0;
|
|
13078
|
+
g1 = initial.g1;
|
|
13079
|
+
};
|
|
13080
|
+
const replace = () => {
|
|
13081
|
+
out.push(REPLACEMENT);
|
|
13082
|
+
bytesUndecodable = true;
|
|
13083
|
+
};
|
|
13084
|
+
let i = 0;
|
|
13085
|
+
while (i < bytes.length) {
|
|
13086
|
+
const byte = at2(bytes, i);
|
|
13087
|
+
if (byte === ESC) {
|
|
13088
|
+
const sequence = matchEscape(bytes, i);
|
|
13089
|
+
if (sequence === void 0) {
|
|
13090
|
+
replace();
|
|
13091
|
+
i = endOfUnrecognizedRun(bytes, i + 1);
|
|
13092
|
+
continue;
|
|
13093
|
+
}
|
|
13094
|
+
if (!declared.has(sequence.ir)) escapeUndeclared = true;
|
|
13095
|
+
if (sequence.element === "G0") g0 = sequence.ir;
|
|
13096
|
+
else g1 = sequence.ir;
|
|
13097
|
+
i += 1 + sequence.tail.length;
|
|
13098
|
+
continue;
|
|
13099
|
+
}
|
|
13100
|
+
if (isLineBreak(byte)) {
|
|
13101
|
+
out.push(String.fromCharCode(byte));
|
|
13102
|
+
reset();
|
|
13103
|
+
i += 1;
|
|
13104
|
+
continue;
|
|
13105
|
+
}
|
|
13106
|
+
if (byte >= 128) {
|
|
13107
|
+
const doubleG1 = g1 === void 0 ? void 0 : DOUBLE_BYTE_SETS.get(g1);
|
|
13108
|
+
if (g1 === void 0 || byte < 160) {
|
|
13109
|
+
replace();
|
|
13110
|
+
i += 1;
|
|
13111
|
+
} else if (doubleG1 !== void 0) {
|
|
13112
|
+
const next = at2(bytes, i + 1);
|
|
13113
|
+
if (isGr94(byte) && isGr94(next)) {
|
|
13114
|
+
const text = pairCharacter(doubleG1, g1, byte, next);
|
|
13115
|
+
if (text === void 0) replace();
|
|
13116
|
+
else out.push(text);
|
|
13117
|
+
i += 2;
|
|
13118
|
+
} else {
|
|
13119
|
+
replace();
|
|
13120
|
+
i += 1;
|
|
13121
|
+
}
|
|
13122
|
+
} else {
|
|
13123
|
+
const text = singleByteCharacter(g1, byte);
|
|
13124
|
+
if (text === void 0) replace();
|
|
13125
|
+
else out.push(text);
|
|
13126
|
+
i += 1;
|
|
13127
|
+
}
|
|
13128
|
+
continue;
|
|
13129
|
+
}
|
|
13130
|
+
if (!isGl(byte)) {
|
|
13131
|
+
out.push(String.fromCharCode(byte));
|
|
13132
|
+
i += 1;
|
|
13133
|
+
continue;
|
|
13134
|
+
}
|
|
13135
|
+
const doubleG0 = DOUBLE_BYTE_SETS.get(g0);
|
|
13136
|
+
if (doubleG0 !== void 0) {
|
|
13137
|
+
const next = at2(bytes, i + 1);
|
|
13138
|
+
if (isGl(next)) {
|
|
13139
|
+
const text = pairCharacter(doubleG0, g0, byte, next);
|
|
13140
|
+
if (text === void 0) replace();
|
|
13141
|
+
else out.push(text);
|
|
13142
|
+
i += 2;
|
|
13143
|
+
} else if (isDelimiter(byte, delimiters)) {
|
|
13144
|
+
out.push(String.fromCharCode(byte));
|
|
13145
|
+
reset();
|
|
13146
|
+
i += 1;
|
|
13147
|
+
} else {
|
|
13148
|
+
replace();
|
|
13149
|
+
i += 1;
|
|
13150
|
+
}
|
|
13151
|
+
continue;
|
|
13152
|
+
}
|
|
13153
|
+
if (isDelimiter(byte, delimiters)) {
|
|
13154
|
+
out.push(String.fromCharCode(byte));
|
|
13155
|
+
reset();
|
|
13156
|
+
i += 1;
|
|
13157
|
+
continue;
|
|
13158
|
+
}
|
|
13159
|
+
let end = i + 1;
|
|
13160
|
+
while (end < bytes.length) {
|
|
13161
|
+
const b = at2(bytes, end);
|
|
13162
|
+
if (b < SPACE || b >= DEL || isDelimiter(b, delimiters)) break;
|
|
13163
|
+
end += 1;
|
|
13164
|
+
}
|
|
13165
|
+
out.push(bytes.toString("latin1", i, end));
|
|
13166
|
+
i = end;
|
|
13167
|
+
}
|
|
13168
|
+
if (g0 !== initial.g0) extensionNotReset = true;
|
|
13169
|
+
return { text: out.join(""), escapeUndeclared, bytesUndecodable, extensionNotReset };
|
|
12489
13170
|
}
|
|
12490
|
-
|
|
12491
|
-
|
|
13171
|
+
|
|
13172
|
+
// src/dataset/vr/charset.ts
|
|
13173
|
+
var TERM_TO_LABEL = /* @__PURE__ */ new Map([
|
|
13174
|
+
// Default repertoire (ISO 646 IRV / ASCII). Latin-1 is a lenient,
|
|
13175
|
+
// never-throws 1:1 superset for the ASCII range.
|
|
13176
|
+
["", "latin1"],
|
|
13177
|
+
["ISO_IR 6", "latin1"],
|
|
13178
|
+
["ISO 2022 IR 6", "latin1"],
|
|
13179
|
+
// Single-byte Latin / Cyrillic / Arabic / Greek / Hebrew / Thai.
|
|
13180
|
+
["ISO_IR 100", "latin1"],
|
|
13181
|
+
["ISO 2022 IR 100", "latin1"],
|
|
13182
|
+
["ISO_IR 101", "iso-8859-2"],
|
|
13183
|
+
["ISO 2022 IR 101", "iso-8859-2"],
|
|
13184
|
+
["ISO_IR 109", "iso-8859-3"],
|
|
13185
|
+
["ISO 2022 IR 109", "iso-8859-3"],
|
|
13186
|
+
["ISO_IR 110", "iso-8859-4"],
|
|
13187
|
+
["ISO 2022 IR 110", "iso-8859-4"],
|
|
13188
|
+
["ISO_IR 144", "iso-8859-5"],
|
|
13189
|
+
["ISO 2022 IR 144", "iso-8859-5"],
|
|
13190
|
+
["ISO_IR 127", "iso-8859-6"],
|
|
13191
|
+
["ISO 2022 IR 127", "iso-8859-6"],
|
|
13192
|
+
["ISO_IR 126", "iso-8859-7"],
|
|
13193
|
+
["ISO 2022 IR 126", "iso-8859-7"],
|
|
13194
|
+
["ISO_IR 138", "iso-8859-8"],
|
|
13195
|
+
["ISO 2022 IR 138", "iso-8859-8"],
|
|
13196
|
+
["ISO_IR 148", "iso-8859-9"],
|
|
13197
|
+
["ISO 2022 IR 148", "iso-8859-9"],
|
|
13198
|
+
["ISO_IR 203", "iso-8859-15"],
|
|
13199
|
+
["ISO 2022 IR 203", "iso-8859-15"],
|
|
13200
|
+
["ISO_IR 13", "shift_jis"],
|
|
13201
|
+
["ISO 2022 IR 13", "shift_jis"],
|
|
13202
|
+
["ISO_IR 166", "windows-874"],
|
|
13203
|
+
["ISO 2022 IR 166", "windows-874"],
|
|
13204
|
+
// Unicode / Chinese single-shot.
|
|
13205
|
+
["ISO_IR 192", "utf-8"],
|
|
13206
|
+
["GB18030", "gb18030"],
|
|
13207
|
+
["GBK", "gbk"],
|
|
13208
|
+
// Multibyte code-extension terms (no bare ISO_IR form).
|
|
13209
|
+
["ISO 2022 IR 87", "iso-2022-jp"],
|
|
13210
|
+
["ISO 2022 IR 159", "iso-2022-jp"],
|
|
13211
|
+
["ISO 2022 IR 149", "euc-kr"],
|
|
13212
|
+
["ISO 2022 IR 58", "gb18030"]
|
|
13213
|
+
]);
|
|
13214
|
+
var MULTIBYTE_LABELS = /* @__PURE__ */ new Set([
|
|
13215
|
+
"utf-8",
|
|
13216
|
+
"iso-2022-jp",
|
|
13217
|
+
"euc-kr",
|
|
13218
|
+
"gb18030",
|
|
13219
|
+
"gbk",
|
|
13220
|
+
"shift_jis"
|
|
13221
|
+
]);
|
|
13222
|
+
function parseSpecificCharacterSet(bytes) {
|
|
13223
|
+
const raw = bytes.toString("latin1");
|
|
13224
|
+
return raw.split("\\").map((t) => t.replace(/[ ]+$/u, "").replace(/^[ ]+/u, "")).map((t) => t === "" || TERM_TO_LABEL.has(t) ? t : WITHHELD);
|
|
12492
13225
|
}
|
|
12493
|
-
function
|
|
12494
|
-
return
|
|
13226
|
+
function isKnownCharsetTerm(term) {
|
|
13227
|
+
return TERM_TO_LABEL.has(term);
|
|
12495
13228
|
}
|
|
12496
|
-
function
|
|
12497
|
-
|
|
13229
|
+
function resolveDecoderLabel(terms) {
|
|
13230
|
+
if (terms === void 0 || terms.length === 0) return "latin1";
|
|
13231
|
+
let firstKnown;
|
|
13232
|
+
for (const term of terms) {
|
|
13233
|
+
const label = TERM_TO_LABEL.get(term);
|
|
13234
|
+
if (label === void 0) continue;
|
|
13235
|
+
if (MULTIBYTE_LABELS.has(label)) return label;
|
|
13236
|
+
firstKnown ??= label;
|
|
13237
|
+
}
|
|
13238
|
+
return firstKnown ?? "latin1";
|
|
12498
13239
|
}
|
|
12499
|
-
function
|
|
12500
|
-
return
|
|
13240
|
+
function decodeText(bytes, terms) {
|
|
13241
|
+
if (usesCodeExtensions(terms)) return decodeWithCodeExtensions(bytes, terms, "text").text;
|
|
13242
|
+
const label = resolveDecoderLabel(terms);
|
|
13243
|
+
try {
|
|
13244
|
+
return new TextDecoder(label, { fatal: false }).decode(bytes);
|
|
13245
|
+
} catch {
|
|
13246
|
+
try {
|
|
13247
|
+
return new TextDecoder("utf-8", { fatal: false }).decode(bytes);
|
|
13248
|
+
} catch {
|
|
13249
|
+
return bytes.toString("latin1");
|
|
13250
|
+
}
|
|
13251
|
+
}
|
|
12501
13252
|
}
|
|
12502
13253
|
|
|
12503
13254
|
// src/profiles/lookup.ts
|
|
@@ -13024,16 +13775,16 @@ function parsePersonName(value) {
|
|
|
13024
13775
|
// src/dataset/vr/decode.ts
|
|
13025
13776
|
var BINARY_VRS = /* @__PURE__ */ new Set(["OB", "OD", "OF", "OL", "OV", "OW", "UN"]);
|
|
13026
13777
|
var NUMBER_VRS = /* @__PURE__ */ new Set(["US", "UL", "SS", "SL", "FL", "FD"]);
|
|
13027
|
-
var
|
|
13778
|
+
var SPACE2 = 32;
|
|
13028
13779
|
var NULL = 0;
|
|
13029
13780
|
function stripPad(bytes, tag, vr, position, warnings) {
|
|
13030
13781
|
let end = bytes.length;
|
|
13031
13782
|
if (vr === "UI") {
|
|
13032
|
-
if (end > 0 && bytes[end - 1] ===
|
|
13033
|
-
while (end > 0 && (bytes[end - 1] === NULL || bytes[end - 1] ===
|
|
13783
|
+
if (end > 0 && bytes[end - 1] === SPACE2) warnings.push(uiTrailingSpace(position, tag));
|
|
13784
|
+
while (end > 0 && (bytes[end - 1] === NULL || bytes[end - 1] === SPACE2)) end--;
|
|
13034
13785
|
} else {
|
|
13035
13786
|
if (end > 0 && bytes[end - 1] === NULL) warnings.push(trailingNullInTextVR(position, tag, vr));
|
|
13036
|
-
while (end > 0 && (bytes[end - 1] ===
|
|
13787
|
+
while (end > 0 && (bytes[end - 1] === SPACE2 || bytes[end - 1] === NULL)) end--;
|
|
13037
13788
|
}
|
|
13038
13789
|
return bytes.subarray(0, end);
|
|
13039
13790
|
}
|
|
@@ -13049,13 +13800,23 @@ function decodeAsciiString(bytes, tag, vr, position, warnings) {
|
|
|
13049
13800
|
}
|
|
13050
13801
|
return bytes.toString("latin1");
|
|
13051
13802
|
}
|
|
13803
|
+
function delimiterClass(vr) {
|
|
13804
|
+
if (vr === "PN") return "personName";
|
|
13805
|
+
if (vr === "LO" || vr === "SH" || vr === "UC") return "multiValued";
|
|
13806
|
+
return "text";
|
|
13807
|
+
}
|
|
13052
13808
|
function decodeCharsetString(bytes, tag, vr, charset, position, warnings) {
|
|
13053
13809
|
let b = bytes;
|
|
13054
13810
|
if (b.length >= 3 && b[0] === 239 && b[1] === 187 && b[2] === 191) {
|
|
13055
13811
|
warnings.push(bomInTextVR(position, tag, vr));
|
|
13056
13812
|
b = b.subarray(3);
|
|
13057
13813
|
}
|
|
13058
|
-
return decodeText(b, charset);
|
|
13814
|
+
if (!usesCodeExtensions(charset)) return decodeText(b, charset);
|
|
13815
|
+
const decoded = decodeWithCodeExtensions(b, charset, delimiterClass(vr));
|
|
13816
|
+
if (decoded.escapeUndeclared) warnings.push(charsetEscapeUndeclared(position, tag, vr));
|
|
13817
|
+
if (decoded.bytesUndecodable) warnings.push(charsetBytesUndecodable(position, tag, vr));
|
|
13818
|
+
if (decoded.extensionNotReset) warnings.push(charsetExtensionNotReset(position, tag, vr));
|
|
13819
|
+
return decoded.text;
|
|
13059
13820
|
}
|
|
13060
13821
|
function decodeElementValue(element) {
|
|
13061
13822
|
const { vr, rawBytes, tag } = element;
|
|
@@ -13155,10 +13916,10 @@ var Element = class {
|
|
|
13155
13916
|
byteOffset;
|
|
13156
13917
|
privateCreator;
|
|
13157
13918
|
/**
|
|
13158
|
-
*
|
|
13159
|
-
*
|
|
13160
|
-
*
|
|
13161
|
-
*
|
|
13919
|
+
* Hint for the lazy SQ decoder. `true` when this Element was promoted
|
|
13920
|
+
* from `VR=UN` with undefined length to `VR=SQ` via the CP-246 fallback,
|
|
13921
|
+
* which is what selects the Implicit VR LE inner decoder. Always
|
|
13922
|
+
* `undefined` on standard SQ elements.
|
|
13162
13923
|
*
|
|
13163
13924
|
* @internal
|
|
13164
13925
|
*/
|
|
@@ -13172,9 +13933,9 @@ var Element = class {
|
|
|
13172
13933
|
/** Lazily-decoded, memoized {@link DicomValue}. */
|
|
13173
13934
|
_valueCache;
|
|
13174
13935
|
/**
|
|
13175
|
-
* Construct a new structural `Element`.
|
|
13176
|
-
*
|
|
13177
|
-
*
|
|
13936
|
+
* Construct a new structural `Element`. The parser builds these directly
|
|
13937
|
+
* from on-wire bytes; consumers receive them via `Dataset` after
|
|
13938
|
+
* `parseDicom`.
|
|
13178
13939
|
*
|
|
13179
13940
|
* @internal
|
|
13180
13941
|
*/
|
|
@@ -13222,15 +13983,38 @@ function defineElement(elements, element, emit) {
|
|
|
13222
13983
|
// src/dataset/item.ts
|
|
13223
13984
|
var Item = class extends Dataset {
|
|
13224
13985
|
index;
|
|
13986
|
+
/**
|
|
13987
|
+
* Byte offset of this Item's `(FFFE,E000)` Item tag in the Part 10 file it
|
|
13988
|
+
* was read from, counted from the first byte of the File Preamble, which is
|
|
13989
|
+
* how PS3.3 2026d Table F.3-3 counts a DICOMDIR's offsets. For a file read
|
|
13990
|
+
* without a preamble, the 132 bytes of File Preamble and `DICM` prefix it
|
|
13991
|
+
* lacks are still counted, so the File Meta group's first byte is offset 132.
|
|
13992
|
+
*
|
|
13993
|
+
* `undefined` for an Item with no position in a file: one inside a Deflated
|
|
13994
|
+
* Data Set (a byte of a deflated stream is not a byte of the file), and one
|
|
13995
|
+
* built by hand. `deidentify()` carries it from each source Item to the Item
|
|
13996
|
+
* it rebuilds, as that Item's identity: it is how `serializeDicom` ties a
|
|
13997
|
+
* DICOMDIR offset to the Directory Record it named.
|
|
13998
|
+
*
|
|
13999
|
+
* @example
|
|
14000
|
+
* ```ts
|
|
14001
|
+
* import { parseDicom } from "@cosyte/dicom";
|
|
14002
|
+
* const ds = parseDicom(buf);
|
|
14003
|
+
* const first = ds.get("00041220")?.items?.[0];
|
|
14004
|
+
* first?.fileOffset; // where that Directory Record Item starts in the file
|
|
14005
|
+
* ```
|
|
14006
|
+
*/
|
|
14007
|
+
fileOffset;
|
|
13225
14008
|
/**
|
|
13226
14009
|
* Construct a new structural `Item`. Producers are the SQ / FFFE
|
|
13227
|
-
* marker parsers
|
|
14010
|
+
* marker parsers.
|
|
13228
14011
|
*
|
|
13229
14012
|
* @internal
|
|
13230
14013
|
*/
|
|
13231
14014
|
constructor(init) {
|
|
13232
14015
|
super(init);
|
|
13233
14016
|
this.index = init.index;
|
|
14017
|
+
this.fileOffset = init.fileOffset;
|
|
13234
14018
|
}
|
|
13235
14019
|
};
|
|
13236
14020
|
|
|
@@ -13284,19 +14068,25 @@ function parseSequence(buffer, valueStart, ctx, emit, opts) {
|
|
|
13284
14068
|
throw err;
|
|
13285
14069
|
}
|
|
13286
14070
|
const itemTag = joinTag(group, element);
|
|
14071
|
+
const fileOffset = fileOffsetIn(ctx.frame, itemHeaderStart);
|
|
14072
|
+
const itemPosition = fileOffset !== void 0 ? { fileOffset } : {};
|
|
13287
14073
|
if (itemTag === SEQ_DELIM_TAG) {
|
|
13288
|
-
return { items, endOffset: cursor.position };
|
|
14074
|
+
return { items, endOffset: cursor.position, delimited: true };
|
|
13289
14075
|
}
|
|
13290
14076
|
if (itemTag !== ITEM_TAG) {
|
|
13291
14077
|
throw unexpectedTagInsideSequence(ctx.frame, itemHeaderStart);
|
|
13292
14078
|
}
|
|
13293
14079
|
if (itemLength === 0) {
|
|
13294
|
-
|
|
14080
|
+
const emptyBasicOffsetTable = opts.encapsulatedPixelData === true && itemIndex === 0;
|
|
14081
|
+
if (!emptyBasicOffsetTable) {
|
|
14082
|
+
emit(emptyItemInSequence({ byteOffset: itemHeaderStart }, itemTag));
|
|
14083
|
+
}
|
|
13295
14084
|
items.push(
|
|
13296
14085
|
new Item({
|
|
13297
14086
|
warnings: [],
|
|
13298
14087
|
elements: /* @__PURE__ */ new Map(),
|
|
13299
|
-
index: itemIndex
|
|
14088
|
+
index: itemIndex,
|
|
14089
|
+
...itemPosition
|
|
13300
14090
|
})
|
|
13301
14091
|
);
|
|
13302
14092
|
itemIndex += 1;
|
|
@@ -13307,7 +14097,9 @@ function parseSequence(buffer, valueStart, ctx, emit, opts) {
|
|
|
13307
14097
|
throw encapsulatedFragmentExceedsBuffer(ctx.frame, itemHeaderStart);
|
|
13308
14098
|
}
|
|
13309
14099
|
cursor.position += itemLength;
|
|
13310
|
-
items.push(
|
|
14100
|
+
items.push(
|
|
14101
|
+
new Item({ warnings: [], elements: /* @__PURE__ */ new Map(), index: itemIndex, ...itemPosition })
|
|
14102
|
+
);
|
|
13311
14103
|
itemIndex += 1;
|
|
13312
14104
|
continue;
|
|
13313
14105
|
}
|
|
@@ -13317,7 +14109,14 @@ function parseSequence(buffer, valueStart, ctx, emit, opts) {
|
|
|
13317
14109
|
const inner = opts.innerStrategy(buffer, cursor.position, ctx, emit, {
|
|
13318
14110
|
stopOnItemDelim: true
|
|
13319
14111
|
});
|
|
13320
|
-
items.push(
|
|
14112
|
+
items.push(
|
|
14113
|
+
new Item({
|
|
14114
|
+
warnings: [],
|
|
14115
|
+
elements: inner.elements,
|
|
14116
|
+
index: itemIndex,
|
|
14117
|
+
...itemPosition
|
|
14118
|
+
})
|
|
14119
|
+
);
|
|
13321
14120
|
cursor.position = inner.endOffset;
|
|
13322
14121
|
} else {
|
|
13323
14122
|
if (opts.explicitLength !== void 0 && endLimit < buffer.length && cursor.position + itemLength > endLimit) {
|
|
@@ -13330,17 +14129,24 @@ function parseSequence(buffer, valueStart, ctx, emit, opts) {
|
|
|
13330
14129
|
const enclosingFrame = ctx.frame;
|
|
13331
14130
|
let inner;
|
|
13332
14131
|
try {
|
|
13333
|
-
ctx.frame =
|
|
14132
|
+
ctx.frame = valueSliceFrame(enclosingFrame, itemSlice, cursor.position);
|
|
13334
14133
|
inner = opts.innerStrategy(itemSlice, 0, ctx, emit);
|
|
13335
14134
|
} finally {
|
|
13336
14135
|
ctx.frame = enclosingFrame;
|
|
13337
14136
|
}
|
|
13338
|
-
items.push(
|
|
14137
|
+
items.push(
|
|
14138
|
+
new Item({
|
|
14139
|
+
warnings: [],
|
|
14140
|
+
elements: inner.elements,
|
|
14141
|
+
index: itemIndex,
|
|
14142
|
+
...itemPosition
|
|
14143
|
+
})
|
|
14144
|
+
);
|
|
13339
14145
|
cursor.position += itemLength;
|
|
13340
14146
|
}
|
|
13341
14147
|
itemIndex += 1;
|
|
13342
14148
|
}
|
|
13343
|
-
return { items, endOffset: cursor.position };
|
|
14149
|
+
return { items, endOffset: cursor.position, delimited: false };
|
|
13344
14150
|
} finally {
|
|
13345
14151
|
ctx.nestingDepth -= 1;
|
|
13346
14152
|
ctx.encodingContextStack.pop();
|
|
@@ -13361,7 +14167,7 @@ function tryParseDefinedLengthSQ(buffer, valueStart, valueLength, ctx, emit, imp
|
|
|
13361
14167
|
const enclosingFrame = ctx.frame;
|
|
13362
14168
|
let result;
|
|
13363
14169
|
try {
|
|
13364
|
-
ctx.frame =
|
|
14170
|
+
ctx.frame = valueSliceFrame(enclosingFrame, slice, valueStart);
|
|
13365
14171
|
result = parseSequence(slice, 0, ctx, emit, {
|
|
13366
14172
|
explicitLength: valueLength,
|
|
13367
14173
|
littleEndian: true,
|
|
@@ -13393,13 +14199,13 @@ function tryParseUnAsSQ(buffer, valueStart, valueLength, ctx, emit, implicitLeIn
|
|
|
13393
14199
|
const opts = {
|
|
13394
14200
|
explicitLength: valueLength === UNDEFINED_LENGTH ? void 0 : valueLength,
|
|
13395
14201
|
littleEndian: true,
|
|
13396
|
-
// CP-246: Implicit VR LE
|
|
14202
|
+
// CP-246: the inner encoding is Implicit VR LE.
|
|
13397
14203
|
innerStrategy: implicitLeInner
|
|
13398
14204
|
};
|
|
13399
14205
|
const enclosingFrame = ctx.frame;
|
|
13400
14206
|
let result;
|
|
13401
14207
|
try {
|
|
13402
|
-
ctx.frame =
|
|
14208
|
+
ctx.frame = valueSliceFrame(enclosingFrame, slice, valueStart);
|
|
13403
14209
|
result = parseSequence(slice, 0, ctx, emit, opts);
|
|
13404
14210
|
} finally {
|
|
13405
14211
|
ctx.frame = enclosingFrame;
|
|
@@ -13568,7 +14374,7 @@ function parseImplicitLE(buffer, datasetStart, ctx, emit, opts = {}) {
|
|
|
13568
14374
|
new Element({
|
|
13569
14375
|
tag,
|
|
13570
14376
|
vr,
|
|
13571
|
-
//
|
|
14377
|
+
// Placeholder - the value decoders derive VM from VR + value layout.
|
|
13572
14378
|
vm: 1,
|
|
13573
14379
|
length,
|
|
13574
14380
|
rawBytes: valueSlice,
|
|
@@ -13689,14 +14495,19 @@ function _parseExplicit(buffer, datasetStart, ctx, emit, mode, opts = {}) {
|
|
|
13689
14495
|
encapsulatedPixelData: true
|
|
13690
14496
|
};
|
|
13691
14497
|
const result = parseSequence(buffer, valueStart2, ctx, emit, seqOpts);
|
|
14498
|
+
if (!result.delimited) {
|
|
14499
|
+
emit(pixelDataFragmentsNotDelimited(position));
|
|
14500
|
+
}
|
|
13692
14501
|
cursor.position = result.endOffset;
|
|
13693
14502
|
const rawBytes = ctx.copyValues ? copyValueBytes(buffer.subarray(headerStart, cursor.position)) : buffer.subarray(headerStart, cursor.position);
|
|
13694
14503
|
defineElement(
|
|
13695
14504
|
elements,
|
|
13696
14505
|
new Element({
|
|
13697
14506
|
tag,
|
|
14507
|
+
// NOT promoted: the value stays `binary` over the whole on-wire span.
|
|
14508
|
+
// `readPixelDataFragments` walks that span for the Basic Offset Table
|
|
14509
|
+
// and the fragments.
|
|
13698
14510
|
vr: "OB",
|
|
13699
|
-
// NOT promoted; Phase 4 surfaces fragments.
|
|
13700
14511
|
vm: result.items.length,
|
|
13701
14512
|
length: UNDEFINED_LENGTH2,
|
|
13702
14513
|
rawBytes,
|
|
@@ -13787,7 +14598,7 @@ function _parseExplicit(buffer, datasetStart, ctx, emit, mode, opts = {}) {
|
|
|
13787
14598
|
new Element({
|
|
13788
14599
|
tag,
|
|
13789
14600
|
vr: finalVr,
|
|
13790
|
-
//
|
|
14601
|
+
// Placeholder - the value decoders derive VM from VR + value layout.
|
|
13791
14602
|
vm: 1,
|
|
13792
14603
|
length,
|
|
13793
14604
|
rawBytes: valueSlice,
|
|
@@ -13859,8 +14670,28 @@ function parseExplicitBE(buffer, datasetStart, ctx, emit, opts = {}) {
|
|
|
13859
14670
|
);
|
|
13860
14671
|
}
|
|
13861
14672
|
|
|
14673
|
+
// src/parser/jpip-referenced.ts
|
|
14674
|
+
var JPIP_REFERENCED_EXPLICIT_LE_UIDS = Object.freeze([
|
|
14675
|
+
"1.2.840.10008.1.2.4.94",
|
|
14676
|
+
"1.2.840.10008.1.2.4.204"
|
|
14677
|
+
]);
|
|
14678
|
+
var JPIP_REFERENCED_DEFLATE_UIDS = Object.freeze([
|
|
14679
|
+
"1.2.840.10008.1.2.4.95",
|
|
14680
|
+
"1.2.840.10008.1.2.4.205"
|
|
14681
|
+
]);
|
|
14682
|
+
var JPIP_REFERENCED_UIDS = Object.freeze([
|
|
14683
|
+
...JPIP_REFERENCED_EXPLICIT_LE_UIDS,
|
|
14684
|
+
...JPIP_REFERENCED_DEFLATE_UIDS
|
|
14685
|
+
]);
|
|
14686
|
+
|
|
13862
14687
|
// src/parser/transfer-syntax.ts
|
|
14688
|
+
function entriesFor(uids, strategy) {
|
|
14689
|
+
return uids.map((uid2) => [uid2, strategy]);
|
|
14690
|
+
}
|
|
13863
14691
|
var TRANSFER_SYNTAX_PARSERS = Object.freeze({
|
|
14692
|
+
...Object.fromEntries(entriesFor(ENCAPSULATED_TRANSFER_SYNTAX_UIDS, parseExplicitLE)),
|
|
14693
|
+
...Object.fromEntries(entriesFor(JPIP_REFERENCED_EXPLICIT_LE_UIDS, parseExplicitLE)),
|
|
14694
|
+
...Object.fromEntries(entriesFor(JPIP_REFERENCED_DEFLATE_UIDS, parseDeflatedLE)),
|
|
13864
14695
|
"1.2.840.10008.1.2": parseImplicitLE,
|
|
13865
14696
|
"1.2.840.10008.1.2.1": parseExplicitLE,
|
|
13866
14697
|
"1.2.840.10008.1.2.2": parseExplicitBE,
|
|
@@ -13868,6 +14699,7 @@ var TRANSFER_SYNTAX_PARSERS = Object.freeze({
|
|
|
13868
14699
|
});
|
|
13869
14700
|
|
|
13870
14701
|
// src/parser/index.ts
|
|
14702
|
+
var PREAMBLE_AND_PREFIX_LENGTH = 132;
|
|
13871
14703
|
function parseDicom(input, options = {}) {
|
|
13872
14704
|
if (rawInputIsEmpty(input)) {
|
|
13873
14705
|
throw emptyInput();
|
|
@@ -13879,7 +14711,8 @@ function parseDicom(input, options = {}) {
|
|
|
13879
14711
|
const warnings = [];
|
|
13880
14712
|
const ctx = buildContext(buffer, options, warnings);
|
|
13881
14713
|
const emit = makeEmitter(ctx);
|
|
13882
|
-
const { datasetStart } = parsePart10Header(buffer, ctx, emit);
|
|
14714
|
+
const { datasetStart, hadPreamble } = parsePart10Header(buffer, ctx, emit);
|
|
14715
|
+
ctx.frame = { ...ctx.frame, origin: hadPreamble ? 0 : PREAMBLE_AND_PREFIX_LENGTH };
|
|
13883
14716
|
const { fileMeta, fileMetaEnd } = parseFileMeta(buffer, datasetStart, ctx, emit);
|
|
13884
14717
|
const tsUid = fileMeta.transferSyntaxUID;
|
|
13885
14718
|
const strategy = TRANSFER_SYNTAX_PARSERS[tsUid];
|
|
@@ -13887,6 +14720,11 @@ function parseDicom(input, options = {}) {
|
|
|
13887
14720
|
throw unsupportedTransferSyntax(ctx.frame, fileMetaEnd, tsUid);
|
|
13888
14721
|
}
|
|
13889
14722
|
const { elements } = strategy(buffer, fileMetaEnd, ctx, emit);
|
|
14723
|
+
emitDirectoryFindings(
|
|
14724
|
+
{ fileMeta, get: (tag) => elements.get(tag) },
|
|
14725
|
+
{ origin: hadPreamble ? 0 : PREAMBLE_AND_PREFIX_LENGTH, fileMetaEnd },
|
|
14726
|
+
emit
|
|
14727
|
+
);
|
|
13890
14728
|
return new Dataset({ fileMeta, warnings: ctx.warnings, elements });
|
|
13891
14729
|
}
|
|
13892
14730
|
function rawInputIsEmpty(input) {
|
|
@@ -13936,12 +14774,159 @@ var Sequence = class {
|
|
|
13936
14774
|
this.length = length;
|
|
13937
14775
|
}
|
|
13938
14776
|
};
|
|
14777
|
+
|
|
14778
|
+
// src/dataset/pixel-data.ts
|
|
14779
|
+
var PIXEL_DATA = "7FE00010";
|
|
13939
14780
|
var UNDEFINED_LENGTH3 = 4294967295;
|
|
14781
|
+
var ELEMENT_HEADER_LENGTH = 12;
|
|
14782
|
+
var ITEM_HEADER_LENGTH = 8;
|
|
14783
|
+
var ITEM_GROUP = 65534;
|
|
14784
|
+
var ITEM = 57344;
|
|
14785
|
+
var SEQUENCE_DELIMITATION = 57565;
|
|
14786
|
+
function readPixelDataFragments(ds) {
|
|
14787
|
+
const el = ds.get(PIXEL_DATA);
|
|
14788
|
+
if (el === void 0 || !isEncapsulated(el)) return void 0;
|
|
14789
|
+
return walkItems(el);
|
|
14790
|
+
}
|
|
14791
|
+
function isEncapsulated(el) {
|
|
14792
|
+
return el.vr === "OB" && el.length === UNDEFINED_LENGTH3;
|
|
14793
|
+
}
|
|
14794
|
+
function walkItems(el) {
|
|
14795
|
+
const raw = el.rawBytes;
|
|
14796
|
+
const frame = { buffer: raw, name: OFFSET_FRAMES.VALUE_SLICE };
|
|
14797
|
+
const read16 = (at4) => el.littleEndian ? raw.readUInt16LE(at4) : raw.readUInt16BE(at4);
|
|
14798
|
+
const read32 = (at4) => el.littleEndian ? raw.readUInt32LE(at4) : raw.readUInt32BE(at4);
|
|
14799
|
+
let basicOffsetTable;
|
|
14800
|
+
const fragments = [];
|
|
14801
|
+
let at3 = ELEMENT_HEADER_LENGTH;
|
|
14802
|
+
while (at3 < raw.length) {
|
|
14803
|
+
if (at3 + ITEM_HEADER_LENGTH > raw.length) throw sqItemHeaderTruncated(frame, at3);
|
|
14804
|
+
const group = read16(at3);
|
|
14805
|
+
const element = read16(at3 + 2);
|
|
14806
|
+
if (group === ITEM_GROUP && element === SEQUENCE_DELIMITATION) break;
|
|
14807
|
+
if (group !== ITEM_GROUP || element !== ITEM) throw unexpectedTagInsideSequence(frame, at3);
|
|
14808
|
+
const valueStart = at3 + ITEM_HEADER_LENGTH;
|
|
14809
|
+
const valueEnd = valueStart + read32(at3 + 4);
|
|
14810
|
+
if (valueEnd > raw.length) throw encapsulatedFragmentExceedsBuffer(frame, at3);
|
|
14811
|
+
const value = raw.subarray(valueStart, valueEnd);
|
|
14812
|
+
if (basicOffsetTable === void 0) basicOffsetTable = value;
|
|
14813
|
+
else fragments.push(value);
|
|
14814
|
+
at3 = valueEnd;
|
|
14815
|
+
}
|
|
14816
|
+
return { basicOffsetTable, fragments };
|
|
14817
|
+
}
|
|
14818
|
+
|
|
14819
|
+
// src/dataset/vr/date-conversion.ts
|
|
14820
|
+
var FRACTION_DIGITS = /\.(\d+)/u;
|
|
14821
|
+
function pad(value, width) {
|
|
14822
|
+
return String(value).padStart(width, "0");
|
|
14823
|
+
}
|
|
14824
|
+
function fractionDigits(value) {
|
|
14825
|
+
if (!("fractionalSeconds" in value) || value.fractionalSeconds === void 0) return void 0;
|
|
14826
|
+
const digits = FRACTION_DIGITS.exec(value.raw)?.[1];
|
|
14827
|
+
return digits === void 0 || digits === "" ? void 0 : digits;
|
|
14828
|
+
}
|
|
14829
|
+
function millisecondOf(digits) {
|
|
14830
|
+
return Number(`${digits}000`.slice(0, 3));
|
|
14831
|
+
}
|
|
14832
|
+
function isLeapYear(year) {
|
|
14833
|
+
return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
|
|
14834
|
+
}
|
|
14835
|
+
var MONTH_LENGTHS = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
14836
|
+
var MAX_OFFSET_MINUTES = 14 * 60 + 59;
|
|
14837
|
+
function longestDayOfMonth(year, month) {
|
|
14838
|
+
if (month === 2) return year === void 0 || isLeapYear(year) ? 29 : 28;
|
|
14839
|
+
return MONTH_LENGTHS[month - 1] ?? 31;
|
|
14840
|
+
}
|
|
14841
|
+
function withinBounds(value, low, high) {
|
|
14842
|
+
return value === void 0 || Number.isInteger(value) && value >= low && value <= high;
|
|
14843
|
+
}
|
|
14844
|
+
function statesARealCalendarDate(parts) {
|
|
14845
|
+
if (!withinBounds(parts.year, 0, 9999)) return false;
|
|
14846
|
+
if (!withinBounds(parts.month, 1, 12)) return false;
|
|
14847
|
+
if (!withinBounds(parts.hour, 0, 23)) return false;
|
|
14848
|
+
if (!withinBounds(parts.minute, 0, 59)) return false;
|
|
14849
|
+
if (!withinBounds(parts.second, 0, 59)) return false;
|
|
14850
|
+
if (!withinBounds(parts.offsetMinutes, -MAX_OFFSET_MINUTES, MAX_OFFSET_MINUTES)) return false;
|
|
14851
|
+
if (parts.month === void 0) return withinBounds(parts.day, 1, 31);
|
|
14852
|
+
return withinBounds(parts.day, 1, longestDayOfMonth(parts.year, parts.month));
|
|
14853
|
+
}
|
|
14854
|
+
function renderTime(parts, digits) {
|
|
14855
|
+
if (parts.hour === void 0) return void 0;
|
|
14856
|
+
let out = pad(parts.hour, 2);
|
|
14857
|
+
if (parts.minute === void 0) return out;
|
|
14858
|
+
out += `:${pad(parts.minute, 2)}`;
|
|
14859
|
+
if (parts.second === void 0) return out;
|
|
14860
|
+
out += `:${pad(parts.second, 2)}`;
|
|
14861
|
+
return digits === void 0 ? out : `${out}.${digits}`;
|
|
14862
|
+
}
|
|
14863
|
+
function renderBody(parts, digits) {
|
|
14864
|
+
const time = renderTime(parts, digits);
|
|
14865
|
+
if (parts.year === void 0) return time;
|
|
14866
|
+
let out = pad(parts.year, 4);
|
|
14867
|
+
if (parts.month !== void 0) {
|
|
14868
|
+
out += `-${pad(parts.month, 2)}`;
|
|
14869
|
+
if (parts.day !== void 0) out += `-${pad(parts.day, 2)}`;
|
|
14870
|
+
}
|
|
14871
|
+
return time === void 0 ? out : `${out}T${time}`;
|
|
14872
|
+
}
|
|
14873
|
+
function renderOffset(offsetMinutes) {
|
|
14874
|
+
if (offsetMinutes === void 0) return "";
|
|
14875
|
+
if (offsetMinutes === 0) return "Z";
|
|
14876
|
+
const total = Math.abs(offsetMinutes);
|
|
14877
|
+
const sign = offsetMinutes < 0 ? "-" : "+";
|
|
14878
|
+
return `${sign}${pad(Math.trunc(total / 60), 2)}:${pad(total % 60, 2)}`;
|
|
14879
|
+
}
|
|
14880
|
+
function toObject(value) {
|
|
14881
|
+
if (value === void 0 || value === null || !value.valid) return void 0;
|
|
14882
|
+
const year = "year" in value ? value.year : void 0;
|
|
14883
|
+
const month = "month" in value ? value.month : void 0;
|
|
14884
|
+
const day = "day" in value ? value.day : void 0;
|
|
14885
|
+
const hour = "hours" in value ? value.hours : void 0;
|
|
14886
|
+
const minute = "minutes" in value ? value.minutes : void 0;
|
|
14887
|
+
const second = "seconds" in value ? value.seconds : void 0;
|
|
14888
|
+
const digits = fractionDigits(value);
|
|
14889
|
+
const rawOffset = "offsetMinutes" in value ? value.offsetMinutes : void 0;
|
|
14890
|
+
const offsetMinutes = rawOffset === 0 ? 0 : rawOffset;
|
|
14891
|
+
const parts = {
|
|
14892
|
+
...year !== void 0 ? { year } : {},
|
|
14893
|
+
...month !== void 0 ? { month } : {},
|
|
14894
|
+
...day !== void 0 ? { day } : {},
|
|
14895
|
+
...hour !== void 0 ? { hour } : {},
|
|
14896
|
+
...minute !== void 0 ? { minute } : {},
|
|
14897
|
+
...second !== void 0 ? { second } : {},
|
|
14898
|
+
...digits !== void 0 ? { millisecond: millisecondOf(digits) } : {},
|
|
14899
|
+
...offsetMinutes !== void 0 ? { offsetMinutes } : {}
|
|
14900
|
+
};
|
|
14901
|
+
if (Object.keys(parts).length === 0) return void 0;
|
|
14902
|
+
if (!statesARealCalendarDate(parts)) return void 0;
|
|
14903
|
+
return Object.freeze(parts);
|
|
14904
|
+
}
|
|
14905
|
+
function toISO(value) {
|
|
14906
|
+
if (value === void 0 || value === null) return void 0;
|
|
14907
|
+
const parts = toObject(value);
|
|
14908
|
+
if (parts === void 0) return void 0;
|
|
14909
|
+
const body = renderBody(parts, fractionDigits(value));
|
|
14910
|
+
return body === void 0 ? void 0 : `${body}${renderOffset(parts.offsetMinutes)}`;
|
|
14911
|
+
}
|
|
14912
|
+
function toDate(value, options) {
|
|
14913
|
+
if (value === void 0 || value === null) return void 0;
|
|
14914
|
+
const parts = toObject(value);
|
|
14915
|
+
if (parts?.year === void 0) return void 0;
|
|
14916
|
+
const offsetMinutes = parts.offsetMinutes ?? options?.assumeOffsetMinutes;
|
|
14917
|
+
if (offsetMinutes === void 0 || !Number.isFinite(offsetMinutes)) return void 0;
|
|
14918
|
+
const utc = /* @__PURE__ */ new Date(0);
|
|
14919
|
+
utc.setUTCFullYear(parts.year, (parts.month ?? 1) - 1, parts.day ?? 1);
|
|
14920
|
+
utc.setUTCHours(parts.hour ?? 0, parts.minute ?? 0, parts.second ?? 0, parts.millisecond ?? 0);
|
|
14921
|
+
const instant = new Date(utc.getTime() - offsetMinutes * 6e4);
|
|
14922
|
+
return Number.isNaN(instant.getTime()) ? void 0 : instant;
|
|
14923
|
+
}
|
|
14924
|
+
var UNDEFINED_LENGTH4 = 4294967295;
|
|
13940
14925
|
var NULL_PAD_VRS = /* @__PURE__ */ new Set(["UI", "OB", "OW", "OF", "OD", "OL", "OV", "UN"]);
|
|
13941
14926
|
function padValue(value, vr) {
|
|
13942
14927
|
if (value.length % 2 === 0) return Buffer.from(value);
|
|
13943
|
-
const
|
|
13944
|
-
return Buffer.concat([value, Buffer.from([
|
|
14928
|
+
const pad2 = NULL_PAD_VRS.has(vr) ? 0 : 32;
|
|
14929
|
+
return Buffer.concat([value, Buffer.from([pad2])]);
|
|
13945
14930
|
}
|
|
13946
14931
|
function uint16(n, littleEndian) {
|
|
13947
14932
|
const buf = Buffer.alloc(2);
|
|
@@ -13956,15 +14941,15 @@ function uint32(n, littleEndian) {
|
|
|
13956
14941
|
return buf;
|
|
13957
14942
|
}
|
|
13958
14943
|
function isFullSpanElement(el, encoding) {
|
|
13959
|
-
if (el.length ===
|
|
14944
|
+
if (el.length === UNDEFINED_LENGTH4) return true;
|
|
13960
14945
|
return el.vr === "SQ" && encoding !== "implicit";
|
|
13961
14946
|
}
|
|
13962
|
-
function encodeDatasetElement(el, encoding) {
|
|
14947
|
+
function encodeDatasetElement(el, encoding, rawBytes = el.rawBytes) {
|
|
13963
14948
|
if (isFullSpanElement(el, encoding)) {
|
|
13964
|
-
return Buffer.from(
|
|
14949
|
+
return Buffer.from(rawBytes);
|
|
13965
14950
|
}
|
|
13966
14951
|
const { group, element } = splitTag(el.tag);
|
|
13967
|
-
const value = padValue(
|
|
14952
|
+
const value = padValue(rawBytes, el.vr);
|
|
13968
14953
|
if (encoding === "implicit") {
|
|
13969
14954
|
return Buffer.concat([
|
|
13970
14955
|
uint16(group, true),
|
|
@@ -13973,49 +14958,473 @@ function encodeDatasetElement(el, encoding) {
|
|
|
13973
14958
|
value
|
|
13974
14959
|
]);
|
|
13975
14960
|
}
|
|
13976
|
-
const littleEndian = encoding === "explicitLE";
|
|
13977
|
-
const vrBuf = Buffer.from(el.vr, "ascii");
|
|
13978
|
-
if (LONG_FORM_VRS.has(el.vr) || !isRecognizedVr(el.vr)) {
|
|
13979
|
-
return Buffer.concat([
|
|
13980
|
-
uint16(group, littleEndian),
|
|
13981
|
-
uint16(element, littleEndian),
|
|
13982
|
-
vrBuf,
|
|
13983
|
-
Buffer.from([0, 0]),
|
|
13984
|
-
// reserved (PS3.5 §7.1.2)
|
|
13985
|
-
uint32(value.length, littleEndian),
|
|
13986
|
-
value
|
|
13987
|
-
]);
|
|
14961
|
+
const littleEndian = encoding === "explicitLE";
|
|
14962
|
+
const vrBuf = Buffer.from(el.vr, "ascii");
|
|
14963
|
+
if (LONG_FORM_VRS.has(el.vr) || !isRecognizedVr(el.vr)) {
|
|
14964
|
+
return Buffer.concat([
|
|
14965
|
+
uint16(group, littleEndian),
|
|
14966
|
+
uint16(element, littleEndian),
|
|
14967
|
+
vrBuf,
|
|
14968
|
+
Buffer.from([0, 0]),
|
|
14969
|
+
// reserved (PS3.5 §7.1.2)
|
|
14970
|
+
uint32(value.length, littleEndian),
|
|
14971
|
+
value
|
|
14972
|
+
]);
|
|
14973
|
+
}
|
|
14974
|
+
return Buffer.concat([
|
|
14975
|
+
uint16(group, littleEndian),
|
|
14976
|
+
uint16(element, littleEndian),
|
|
14977
|
+
vrBuf,
|
|
14978
|
+
uint16(value.length, littleEndian),
|
|
14979
|
+
value
|
|
14980
|
+
]);
|
|
14981
|
+
}
|
|
14982
|
+
|
|
14983
|
+
// src/serialize/errors.ts
|
|
14984
|
+
var SERIALIZE_ERROR_CODES = {
|
|
14985
|
+
MISSING_TRANSFER_SYNTAX: "MISSING_TRANSFER_SYNTAX",
|
|
14986
|
+
UNSUPPORTED_TRANSFER_SYNTAX: "UNSUPPORTED_TRANSFER_SYNTAX",
|
|
14987
|
+
INVALID_ENCAPSULATED_PIXEL_DATA: "INVALID_ENCAPSULATED_PIXEL_DATA",
|
|
14988
|
+
DIRECTORY_OFFSET_UNRESOLVED: "DIRECTORY_OFFSET_UNRESOLVED",
|
|
14989
|
+
DIRECTORY_OFFSET_DEFLATED: "DIRECTORY_OFFSET_DEFLATED"
|
|
14990
|
+
};
|
|
14991
|
+
var DicomSerializeError = class extends Error {
|
|
14992
|
+
code;
|
|
14993
|
+
/**
|
|
14994
|
+
* Construct a new `DicomSerializeError`. The `message` MUST be built only
|
|
14995
|
+
* from structural facts (never a decoded attribute value) so the error is
|
|
14996
|
+
* always safe to log.
|
|
14997
|
+
*
|
|
14998
|
+
* @internal
|
|
14999
|
+
*/
|
|
15000
|
+
constructor(code, message) {
|
|
15001
|
+
super(`[${code}] ${message}`);
|
|
15002
|
+
this.name = "DicomSerializeError";
|
|
15003
|
+
this.code = code;
|
|
15004
|
+
}
|
|
15005
|
+
};
|
|
15006
|
+
var UNDEFINED_LENGTH5 = 4294967295;
|
|
15007
|
+
var ITEM2 = 4294893568;
|
|
15008
|
+
var ITEM_DELIMITATION = 4294893581;
|
|
15009
|
+
var SEQUENCE_DELIMITATION2 = 4294893789;
|
|
15010
|
+
var PIXEL_DATA2 = "7FE00010";
|
|
15011
|
+
var MARKER_LENGTH = 8;
|
|
15012
|
+
var IMPLICIT_LE = { encoding: "implicit", littleEndian: true, explicitVr: false };
|
|
15013
|
+
var SYNTAX = {
|
|
15014
|
+
implicit: IMPLICIT_LE,
|
|
15015
|
+
explicitLE: { encoding: "explicitLE", littleEndian: true, explicitVr: true },
|
|
15016
|
+
explicitBE: { encoding: "explicitBE", littleEndian: false, explicitVr: true }
|
|
15017
|
+
};
|
|
15018
|
+
function readUint16(buf, offset, littleEndian) {
|
|
15019
|
+
return littleEndian ? buf.readUInt16LE(offset) : buf.readUInt16BE(offset);
|
|
15020
|
+
}
|
|
15021
|
+
function readUint32(buf, offset, littleEndian) {
|
|
15022
|
+
return littleEndian ? buf.readUInt32LE(offset) : buf.readUInt32BE(offset);
|
|
15023
|
+
}
|
|
15024
|
+
function readTagNumber(buf, offset, littleEndian) {
|
|
15025
|
+
return readUint16(buf, offset, littleEndian) * 65536 + readUint16(buf, offset + 2, littleEndian);
|
|
15026
|
+
}
|
|
15027
|
+
function isMarker(tagNumber2) {
|
|
15028
|
+
return tagNumber2 >= 4294836224 && tagNumber2 < 4294901760;
|
|
15029
|
+
}
|
|
15030
|
+
function appendAll(target, source) {
|
|
15031
|
+
for (const part of source) target.push(part);
|
|
15032
|
+
}
|
|
15033
|
+
function tagNumber(tag) {
|
|
15034
|
+
const { group, element } = splitTag(tag);
|
|
15035
|
+
return group * 65536 + element;
|
|
15036
|
+
}
|
|
15037
|
+
function tagOf(tagNumberValue) {
|
|
15038
|
+
return tagNumberValue.toString(16).padStart(8, "0").toUpperCase();
|
|
15039
|
+
}
|
|
15040
|
+
function isImplicitSequence(tagNumberValue) {
|
|
15041
|
+
const group = Math.floor(tagNumberValue / 65536);
|
|
15042
|
+
if (group % 2 === 1) return false;
|
|
15043
|
+
const tag = tagOf(tagNumberValue);
|
|
15044
|
+
const entry = TAGS[tag] ?? matchRepeatingGroup(tag);
|
|
15045
|
+
return entry?.vr[0] === "SQ";
|
|
15046
|
+
}
|
|
15047
|
+
function readElementHeader(buf, p, stop, syntax) {
|
|
15048
|
+
if (p + MARKER_LENGTH > stop) return void 0;
|
|
15049
|
+
const le = syntax.littleEndian;
|
|
15050
|
+
const tag = readTagNumber(buf, p, le);
|
|
15051
|
+
if (!syntax.explicitVr || isMarker(tag)) {
|
|
15052
|
+
return { tag, headerLength: MARKER_LENGTH, length: readUint32(buf, p + 4, le), vr: void 0 };
|
|
15053
|
+
}
|
|
15054
|
+
const vr = buf.toString("ascii", p + 4, p + 6);
|
|
15055
|
+
if (LONG_FORM_VRS.has(vr) || !isRecognizedVr(vr)) {
|
|
15056
|
+
if (p + 12 > stop) return void 0;
|
|
15057
|
+
return { tag, headerLength: 12, length: readUint32(buf, p + 8, le), vr };
|
|
15058
|
+
}
|
|
15059
|
+
return { tag, headerLength: MARKER_LENGTH, length: readUint16(buf, p + 6, le), vr };
|
|
15060
|
+
}
|
|
15061
|
+
function isSequence(header, syntax) {
|
|
15062
|
+
return syntax.explicitVr ? header.vr === "SQ" : isImplicitSequence(header.tag);
|
|
15063
|
+
}
|
|
15064
|
+
function verbatim(buf, start, end) {
|
|
15065
|
+
return { parts: [buf.subarray(start, end)], changed: false, end };
|
|
15066
|
+
}
|
|
15067
|
+
function fragmentsClose(buf, start, littleEndian) {
|
|
15068
|
+
let p = start;
|
|
15069
|
+
while (p + MARKER_LENGTH <= buf.length) {
|
|
15070
|
+
const tag = readTagNumber(buf, p, littleEndian);
|
|
15071
|
+
p += MARKER_LENGTH;
|
|
15072
|
+
if (tag === SEQUENCE_DELIMITATION2) return p === buf.length;
|
|
15073
|
+
if (tag !== ITEM2) return false;
|
|
15074
|
+
p += readUint32(buf, p - 4, littleEndian);
|
|
15075
|
+
}
|
|
15076
|
+
return false;
|
|
15077
|
+
}
|
|
15078
|
+
function closesItself(el, syntax, depth) {
|
|
15079
|
+
const raw = el.rawBytes;
|
|
15080
|
+
const valueStart = syntax.explicitVr ? 12 : MARKER_LENGTH;
|
|
15081
|
+
if (el.cp246Promoted === true || el.vr === "SQ") {
|
|
15082
|
+
if (depth > NESTING_DEPTH_LIMIT) return false;
|
|
15083
|
+
const itemSyntax = el.cp246Promoted === true ? IMPLICIT_LE : syntax;
|
|
15084
|
+
const walked = walkItems2(raw, valueStart, void 0, raw.length, itemSyntax, depth, el.items);
|
|
15085
|
+
return walked?.end === raw.length;
|
|
15086
|
+
}
|
|
15087
|
+
return el.tag === PIXEL_DATA2 && fragmentsClose(raw, valueStart, syntax.littleEndian);
|
|
15088
|
+
}
|
|
15089
|
+
function walkElement(buf, p, stop, syntax, depth, item) {
|
|
15090
|
+
const header = readElementHeader(buf, p, stop, syntax);
|
|
15091
|
+
if (header === void 0) return void 0;
|
|
15092
|
+
const model = item.get(tagOf(header.tag));
|
|
15093
|
+
if (model === void 0) return void 0;
|
|
15094
|
+
const valueStart = p + header.headerLength;
|
|
15095
|
+
const undefinedLength = header.length === UNDEFINED_LENGTH5;
|
|
15096
|
+
const items = depth < NESTING_DEPTH_LIMIT && isSequence(header, syntax) && model.vr === "SQ" ? model.items : void 0;
|
|
15097
|
+
let walked;
|
|
15098
|
+
if (items !== void 0) {
|
|
15099
|
+
const definedEnd = undefinedLength ? void 0 : valueStart + header.length;
|
|
15100
|
+
walked = definedEnd !== void 0 && definedEnd > stop ? void 0 : walkItems2(buf, valueStart, definedEnd, stop, syntax, depth + 1, items);
|
|
15101
|
+
} else {
|
|
15102
|
+
const end = undefinedLength ? p + model.rawBytes.length : valueStart + header.length;
|
|
15103
|
+
walked = end < valueStart || end > stop ? void 0 : verbatim(buf, valueStart, end);
|
|
15104
|
+
}
|
|
15105
|
+
if (walked === void 0) return void 0;
|
|
15106
|
+
const span = {
|
|
15107
|
+
tag: header.tag,
|
|
15108
|
+
start: p,
|
|
15109
|
+
valueStart,
|
|
15110
|
+
undefinedLength,
|
|
15111
|
+
descended: items !== void 0,
|
|
15112
|
+
model
|
|
15113
|
+
};
|
|
15114
|
+
if (!walked.changed) return { ...span, ...verbatim(buf, p, walked.end) };
|
|
15115
|
+
const parts = [buf.subarray(p, valueStart)];
|
|
15116
|
+
appendAll(parts, walked.parts);
|
|
15117
|
+
return { ...span, parts, changed: true, end: walked.end };
|
|
15118
|
+
}
|
|
15119
|
+
function agrees(buf, span, encoding) {
|
|
15120
|
+
const model = span.model;
|
|
15121
|
+
const valueOnly = !isFullSpanElement(model, encoding);
|
|
15122
|
+
const bytes = buf.subarray(valueOnly ? span.valueStart : span.start, span.end);
|
|
15123
|
+
if (span.descended) return model.rawBytes.length === bytes.length;
|
|
15124
|
+
if (model.rawBytes.equals(bytes)) return true;
|
|
15125
|
+
return valueOnly && bytes.length === model.rawBytes.length + 1 && padValue(model.rawBytes, model.vr).equals(bytes);
|
|
15126
|
+
}
|
|
15127
|
+
function walkDataSet(buf, start, definedEnd, limit, syntax, depth, model, placed) {
|
|
15128
|
+
const stop = definedEnd ?? limit;
|
|
15129
|
+
const spans = [];
|
|
15130
|
+
let delimiter;
|
|
15131
|
+
let p = start;
|
|
15132
|
+
while (definedEnd === void 0 || p < definedEnd) {
|
|
15133
|
+
if (p + MARKER_LENGTH > stop) return void 0;
|
|
15134
|
+
const tag = readTagNumber(buf, p, syntax.littleEndian);
|
|
15135
|
+
if (isMarker(tag)) {
|
|
15136
|
+
if (definedEnd !== void 0 || tag !== ITEM_DELIMITATION) return void 0;
|
|
15137
|
+
delimiter = buf.subarray(p, p + MARKER_LENGTH);
|
|
15138
|
+
p += MARKER_LENGTH;
|
|
15139
|
+
break;
|
|
15140
|
+
}
|
|
15141
|
+
const span = walkElement(buf, p, stop, syntax, depth, model);
|
|
15142
|
+
if (span === void 0) return void 0;
|
|
15143
|
+
spans.push(span);
|
|
15144
|
+
p = span.end;
|
|
15145
|
+
}
|
|
15146
|
+
const last = /* @__PURE__ */ new Map();
|
|
15147
|
+
for (const span of spans) last.set(span.tag, span);
|
|
15148
|
+
for (const el of model.elements()) {
|
|
15149
|
+
if (!last.has(tagNumber(el.tag)) && splitTag(el.tag).element !== 0) return void 0;
|
|
15150
|
+
}
|
|
15151
|
+
const closed = [];
|
|
15152
|
+
const open = [];
|
|
15153
|
+
for (const span of spans) {
|
|
15154
|
+
if (last.get(span.tag) !== span) {
|
|
15155
|
+
if (span.undefinedLength) return void 0;
|
|
15156
|
+
closed.push({
|
|
15157
|
+
tag: span.tag,
|
|
15158
|
+
start: span.start,
|
|
15159
|
+
valueStart: span.valueStart,
|
|
15160
|
+
...verbatim(buf, span.start, span.end)
|
|
15161
|
+
});
|
|
15162
|
+
} else if (!agrees(buf, span, syntax.encoding)) {
|
|
15163
|
+
return void 0;
|
|
15164
|
+
} else if (span.descended || !isFullSpanElement(span.model, syntax.encoding) || closesItself(span.model, syntax, depth + 1)) {
|
|
15165
|
+
closed.push(span);
|
|
15166
|
+
} else {
|
|
15167
|
+
open.push(span);
|
|
15168
|
+
}
|
|
15169
|
+
}
|
|
15170
|
+
const ordered = [...closed.sort((a, b) => a.tag - b.tag), ...open];
|
|
15171
|
+
if (placed !== void 0) {
|
|
15172
|
+
let at3 = start;
|
|
15173
|
+
for (const span of ordered) {
|
|
15174
|
+
const length = span.end - span.start;
|
|
15175
|
+
placed.push({
|
|
15176
|
+
tag: span.tag,
|
|
15177
|
+
start: at3,
|
|
15178
|
+
valueStart: at3 + (span.valueStart - span.start),
|
|
15179
|
+
end: at3 + length
|
|
15180
|
+
});
|
|
15181
|
+
at3 += length;
|
|
15182
|
+
}
|
|
15183
|
+
}
|
|
15184
|
+
const moved = ordered.some((span, i) => span.start !== spans[i]?.start);
|
|
15185
|
+
if (!moved && !ordered.some((span) => span.changed)) return verbatim(buf, start, p);
|
|
15186
|
+
const parts = [];
|
|
15187
|
+
for (const span of ordered) appendAll(parts, span.parts);
|
|
15188
|
+
if (delimiter !== void 0) parts.push(delimiter);
|
|
15189
|
+
return { parts, changed: true, end: p };
|
|
15190
|
+
}
|
|
15191
|
+
function walkItems2(buf, start, definedEnd, limit, syntax, depth, items, placements) {
|
|
15192
|
+
if (items === void 0) return void 0;
|
|
15193
|
+
const stop = definedEnd ?? limit;
|
|
15194
|
+
const le = syntax.littleEndian;
|
|
15195
|
+
const parts = [];
|
|
15196
|
+
let changed = false;
|
|
15197
|
+
let index = 0;
|
|
15198
|
+
let p = start;
|
|
15199
|
+
while (definedEnd === void 0 || p < definedEnd) {
|
|
15200
|
+
if (p + MARKER_LENGTH > stop) return void 0;
|
|
15201
|
+
const tag = readTagNumber(buf, p, le);
|
|
15202
|
+
if (tag === SEQUENCE_DELIMITATION2 && definedEnd === void 0) {
|
|
15203
|
+
parts.push(buf.subarray(p, p + MARKER_LENGTH));
|
|
15204
|
+
p += MARKER_LENGTH;
|
|
15205
|
+
break;
|
|
15206
|
+
}
|
|
15207
|
+
const model = items[index];
|
|
15208
|
+
if (tag !== ITEM2 || model === void 0) return void 0;
|
|
15209
|
+
const length = readUint32(buf, p + 4, le);
|
|
15210
|
+
const bodyStart = p + MARKER_LENGTH;
|
|
15211
|
+
const placed = [];
|
|
15212
|
+
const collect = placements !== void 0 ? placed : void 0;
|
|
15213
|
+
let item;
|
|
15214
|
+
if (length === UNDEFINED_LENGTH5) {
|
|
15215
|
+
item = walkDataSet(buf, bodyStart, void 0, stop, syntax, depth, model, collect);
|
|
15216
|
+
} else if (bodyStart + length <= stop) {
|
|
15217
|
+
item = walkDataSet(buf, bodyStart, bodyStart + length, stop, syntax, depth, model, collect);
|
|
15218
|
+
}
|
|
15219
|
+
if (item === void 0) return void 0;
|
|
15220
|
+
placements?.push({ itemStart: p, elements: placed });
|
|
15221
|
+
parts.push(buf.subarray(p, bodyStart));
|
|
15222
|
+
appendAll(parts, item.parts);
|
|
15223
|
+
changed ||= item.changed;
|
|
15224
|
+
p = item.end;
|
|
15225
|
+
index += 1;
|
|
15226
|
+
}
|
|
15227
|
+
if (index !== items.length) return void 0;
|
|
15228
|
+
if (!changed) return verbatim(buf, start, p);
|
|
15229
|
+
return { parts, changed, end: p };
|
|
15230
|
+
}
|
|
15231
|
+
function walkSequence(el, syntax, placements) {
|
|
15232
|
+
const raw = el.rawBytes;
|
|
15233
|
+
let valueStart = 0;
|
|
15234
|
+
let definedEnd = raw.length;
|
|
15235
|
+
if (isFullSpanElement(el, syntax.encoding)) {
|
|
15236
|
+
const header = readElementHeader(raw, 0, raw.length, syntax);
|
|
15237
|
+
if (header === void 0 || syntax.explicitVr && header.vr !== "SQ") return void 0;
|
|
15238
|
+
valueStart = header.headerLength;
|
|
15239
|
+
definedEnd = header.length === UNDEFINED_LENGTH5 ? void 0 : valueStart + header.length;
|
|
15240
|
+
}
|
|
15241
|
+
const walked = walkItems2(
|
|
15242
|
+
raw,
|
|
15243
|
+
valueStart,
|
|
15244
|
+
definedEnd,
|
|
15245
|
+
raw.length,
|
|
15246
|
+
syntax,
|
|
15247
|
+
1,
|
|
15248
|
+
el.items,
|
|
15249
|
+
placements
|
|
15250
|
+
);
|
|
15251
|
+
if (walked?.end !== raw.length) return void 0;
|
|
15252
|
+
if (!walked.changed) return walked;
|
|
15253
|
+
return { parts: [raw.subarray(0, valueStart), ...walked.parts], changed: true, end: raw.length };
|
|
15254
|
+
}
|
|
15255
|
+
function emissionOf(el, encoding, place = false) {
|
|
15256
|
+
const syntax = SYNTAX[encoding];
|
|
15257
|
+
const valueOnly = !isFullSpanElement(el, encoding);
|
|
15258
|
+
if (el.vr !== "SQ" || el.cp246Promoted === true) {
|
|
15259
|
+
return { rawBytes: void 0, closed: valueOnly || closesItself(el, syntax, 1) };
|
|
15260
|
+
}
|
|
15261
|
+
const placements = place ? [] : void 0;
|
|
15262
|
+
const walked = walkSequence(el, syntax, placements);
|
|
15263
|
+
if (walked === void 0) return { rawBytes: void 0, closed: valueOnly };
|
|
15264
|
+
return {
|
|
15265
|
+
rawBytes: walked.changed ? Buffer.concat(walked.parts) : void 0,
|
|
15266
|
+
closed: true,
|
|
15267
|
+
...placements !== void 0 ? { placements } : {}
|
|
15268
|
+
};
|
|
15269
|
+
}
|
|
15270
|
+
|
|
15271
|
+
// src/serialize/directory.ts
|
|
15272
|
+
var PLACED_TAGS = /* @__PURE__ */ new Set([
|
|
15273
|
+
DIRECTORY_TAGS.FIRST_ROOT_RECORD,
|
|
15274
|
+
DIRECTORY_TAGS.LAST_ROOT_RECORD,
|
|
15275
|
+
DIRECTORY_TAGS.RECORD_SEQUENCE
|
|
15276
|
+
]);
|
|
15277
|
+
var RECORD_OFFSET_TAGS = /* @__PURE__ */ new Set([
|
|
15278
|
+
tagNumber(DIRECTORY_TAGS.NEXT_RECORD),
|
|
15279
|
+
tagNumber(DIRECTORY_TAGS.LOWER_LEVEL)
|
|
15280
|
+
]);
|
|
15281
|
+
var IMPLICIT_HEADER_LENGTH = 8;
|
|
15282
|
+
var UNRESOLVED_MESSAGE = "The Dataset is a DICOMDIR and carries a Directory Record offset attribute that the writer cannot tie to a Directory Record the Dataset holds: a non-zero offset that names no Item of the Directory Record Sequence, or a value that is not one unsigned integer of four bytes. Written stale it would name the wrong bytes, and written as zero it would silently prune the tree, so nothing is written.";
|
|
15283
|
+
var DEFLATED_MESSAGE = "The Dataset is a DICOMDIR to be written in Deflated Explicit VR Little Endian and carries a non-zero Directory Record offset. A position inside a deflated stream names no Item a reader can seek to, so nothing is written. A DICOMDIR File is to be written in Explicit VR Little Endian.";
|
|
15284
|
+
function refuse(deflated) {
|
|
15285
|
+
throw deflated ? new DicomSerializeError(SERIALIZE_ERROR_CODES.DIRECTORY_OFFSET_DEFLATED, DEFLATED_MESSAGE) : new DicomSerializeError(
|
|
15286
|
+
SERIALIZE_ERROR_CODES.DIRECTORY_OFFSET_UNRESOLVED,
|
|
15287
|
+
UNRESOLVED_MESSAGE
|
|
15288
|
+
);
|
|
15289
|
+
}
|
|
15290
|
+
function readValue(body, at3, littleEndian) {
|
|
15291
|
+
const value = littleEndian ? body.readUInt32LE(at3) : body.readUInt32BE(at3);
|
|
15292
|
+
return value === 0 ? { kind: "zero" } : { kind: "offset", value };
|
|
15293
|
+
}
|
|
15294
|
+
function rewriteDirectoryOffsets(ds, body, placed, encoding, bodyFileOffset, deflated) {
|
|
15295
|
+
const littleEndian = encoding !== "explicitBE";
|
|
15296
|
+
const { items, byFileOffset } = directoryRecords(ds);
|
|
15297
|
+
const sequence = placed.get(DIRECTORY_TAGS.RECORD_SEQUENCE);
|
|
15298
|
+
const placements = sequence?.placements;
|
|
15299
|
+
const slots = [];
|
|
15300
|
+
for (const tag of [DIRECTORY_TAGS.FIRST_ROOT_RECORD, DIRECTORY_TAGS.LAST_ROOT_RECORD]) {
|
|
15301
|
+
const root = placed.get(tag);
|
|
15302
|
+
if (root === void 0) continue;
|
|
15303
|
+
slots.push({ value: readOffsetValue(root.el), at: root.start + root.bytes.length - 4 });
|
|
15304
|
+
}
|
|
15305
|
+
const rawStart = sequence === void 0 ? 0 : sequence.start + (isFullSpanElement(sequence.el, encoding) ? 0 : IMPLICIT_HEADER_LENGTH);
|
|
15306
|
+
if (placements !== void 0) {
|
|
15307
|
+
for (const placement of placements) {
|
|
15308
|
+
for (const span of placement.elements) {
|
|
15309
|
+
if (!RECORD_OFFSET_TAGS.has(span.tag)) continue;
|
|
15310
|
+
const at3 = rawStart + span.valueStart;
|
|
15311
|
+
const value = span.end - span.valueStart === 4 ? readValue(body, at3, littleEndian) : { kind: "malformed" };
|
|
15312
|
+
slots.push({ value, at: at3 });
|
|
15313
|
+
}
|
|
15314
|
+
}
|
|
15315
|
+
} else {
|
|
15316
|
+
for (const item of items) {
|
|
15317
|
+
for (const tag of [DIRECTORY_TAGS.NEXT_RECORD, DIRECTORY_TAGS.LOWER_LEVEL]) {
|
|
15318
|
+
const el = item.get(tag);
|
|
15319
|
+
if (el !== void 0) slots.push({ value: readOffsetValue(el), at: void 0 });
|
|
15320
|
+
}
|
|
15321
|
+
}
|
|
15322
|
+
}
|
|
15323
|
+
const patches = [];
|
|
15324
|
+
for (const slot of slots) {
|
|
15325
|
+
if (slot.value.kind === "zero") continue;
|
|
15326
|
+
if (slot.value.kind === "malformed" || deflated) refuse(deflated);
|
|
15327
|
+
const target = byFileOffset.get(slot.value.value);
|
|
15328
|
+
const record = target === void 0 ? void 0 : placements?.[target];
|
|
15329
|
+
if (record === void 0 || slot.at === void 0) refuse(false);
|
|
15330
|
+
patches.push({ at: slot.at, value: bodyFileOffset + rawStart + record.itemStart });
|
|
15331
|
+
}
|
|
15332
|
+
for (const patch of patches) {
|
|
15333
|
+
if (littleEndian) body.writeUInt32LE(patch.value, patch.at);
|
|
15334
|
+
else body.writeUInt32BE(patch.value, patch.at);
|
|
15335
|
+
}
|
|
15336
|
+
}
|
|
15337
|
+
var PIXEL_DATA3 = "7FE00010";
|
|
15338
|
+
var FLOAT_PIXEL_DATA = "7FE00008";
|
|
15339
|
+
var DOUBLE_FLOAT_PIXEL_DATA = "7FE00009";
|
|
15340
|
+
var UNDEFINED_LENGTH6 = 4294967295;
|
|
15341
|
+
var ELEMENT_HEADER_LENGTH2 = 12;
|
|
15342
|
+
var ITEM_HEADER_LENGTH2 = 8;
|
|
15343
|
+
var ITEM_GROUP2 = 65534;
|
|
15344
|
+
var ITEM3 = 57344;
|
|
15345
|
+
var SEQUENCE_DELIMITATION3 = 57565;
|
|
15346
|
+
var PIXEL_DATA_HEADER = Buffer.from([
|
|
15347
|
+
224,
|
|
15348
|
+
127,
|
|
15349
|
+
16,
|
|
15350
|
+
0,
|
|
15351
|
+
79,
|
|
15352
|
+
66,
|
|
15353
|
+
0,
|
|
15354
|
+
0,
|
|
15355
|
+
255,
|
|
15356
|
+
255,
|
|
15357
|
+
255,
|
|
15358
|
+
255
|
|
15359
|
+
]);
|
|
15360
|
+
var SEQUENCE_DELIMITATION_ITEM = Buffer.from([
|
|
15361
|
+
254,
|
|
15362
|
+
255,
|
|
15363
|
+
221,
|
|
15364
|
+
224,
|
|
15365
|
+
0,
|
|
15366
|
+
0,
|
|
15367
|
+
0,
|
|
15368
|
+
0
|
|
15369
|
+
]);
|
|
15370
|
+
var MESSAGES = {
|
|
15371
|
+
absent: "A PS3.5 section A.4 Transfer Syntax needs Pixel Data (7FE0,0010) in the top-level Data Set, and it has none.",
|
|
15372
|
+
float: "A PS3.5 section A.4 Transfer Syntax cannot carry Float Pixel Data (7FE0,0008) or Double Float Pixel Data (7FE0,0009) in the top-level Data Set.",
|
|
15373
|
+
native: "Top-level Pixel Data (7FE0,0010) under a PS3.5 section A.4 Transfer Syntax has a defined Value Length (Native Format); it must be Encapsulated Format.",
|
|
15374
|
+
notFragmentSpan: "Top-level Pixel Data (7FE0,0010) is not held as an undefined-length (7FE0,0010) span, so it is not a fragment stream the writer can emit.",
|
|
15375
|
+
notItem: "The top-level Pixel Data fragment stream holds something other than an Item (FFFE,E000) of defined Item Length before its Sequence Delimitation Item.",
|
|
15376
|
+
notDelimited: "The top-level Pixel Data fragment stream does not end on a Sequence Delimitation Item (FFFE,E0DD); the writer does not append one to a stream that may be short.",
|
|
15377
|
+
afterDelimiter: "The top-level Pixel Data span holds bytes after its Sequence Delimitation Item (FFFE,E0DD).",
|
|
15378
|
+
oddLength: "An Item in the top-level Pixel Data fragment stream has an odd Item Length; PS3.5 section A.4 requires an even number of bytes.",
|
|
15379
|
+
emptyFragment: "A fragment Item after the Basic Offset Table in the top-level Pixel Data fragment stream has Item Length zero; PS3.5 section A.4 requires two bytes or more.",
|
|
15380
|
+
noBasicOffsetTable: "The top-level Pixel Data fragment stream holds no Item, so it has no Basic Offset Table Item.",
|
|
15381
|
+
noFragment: "The top-level Pixel Data fragment stream holds a Basic Offset Table Item and no fragment Item."
|
|
15382
|
+
};
|
|
15383
|
+
function refuse2(reason) {
|
|
15384
|
+
throw new DicomSerializeError(
|
|
15385
|
+
SERIALIZE_ERROR_CODES.INVALID_ENCAPSULATED_PIXEL_DATA,
|
|
15386
|
+
MESSAGES[reason]
|
|
15387
|
+
);
|
|
15388
|
+
}
|
|
15389
|
+
function itemStreamEnd(raw) {
|
|
15390
|
+
let at3 = ELEMENT_HEADER_LENGTH2;
|
|
15391
|
+
let items = 0;
|
|
15392
|
+
for (; ; ) {
|
|
15393
|
+
if (at3 + ITEM_HEADER_LENGTH2 > raw.length) refuse2("notDelimited");
|
|
15394
|
+
const group = raw.readUInt16LE(at3);
|
|
15395
|
+
const element = raw.readUInt16LE(at3 + 2);
|
|
15396
|
+
const length = raw.readUInt32LE(at3 + 4);
|
|
15397
|
+
if (group === ITEM_GROUP2 && element === SEQUENCE_DELIMITATION3) break;
|
|
15398
|
+
if (group !== ITEM_GROUP2 || element !== ITEM3 || length === UNDEFINED_LENGTH6) refuse2("notItem");
|
|
15399
|
+
if (length % 2 === 1) refuse2("oddLength");
|
|
15400
|
+
if (length === 0 && items > 0) refuse2("emptyFragment");
|
|
15401
|
+
if (at3 + ITEM_HEADER_LENGTH2 + length > raw.length) refuse2("notDelimited");
|
|
15402
|
+
at3 += ITEM_HEADER_LENGTH2 + length;
|
|
15403
|
+
items += 1;
|
|
15404
|
+
}
|
|
15405
|
+
if (at3 + ITEM_HEADER_LENGTH2 !== raw.length) refuse2("afterDelimiter");
|
|
15406
|
+
if (items === 0) refuse2("noBasicOffsetTable");
|
|
15407
|
+
if (items === 1) refuse2("noFragment");
|
|
15408
|
+
return at3;
|
|
15409
|
+
}
|
|
15410
|
+
function encapsulatedPixelData(ds) {
|
|
15411
|
+
if (ds.has(FLOAT_PIXEL_DATA) || ds.has(DOUBLE_FLOAT_PIXEL_DATA)) refuse2("float");
|
|
15412
|
+
const el = ds.get(PIXEL_DATA3);
|
|
15413
|
+
if (el === void 0) refuse2("absent");
|
|
15414
|
+
if (el.length !== UNDEFINED_LENGTH6) refuse2("native");
|
|
15415
|
+
const raw = el.rawBytes;
|
|
15416
|
+
if (raw.length < ELEMENT_HEADER_LENGTH2 || raw.readUInt16LE(0) !== 32736 || raw.readUInt16LE(2) !== 16 || raw.readUInt32LE(8) !== UNDEFINED_LENGTH6) {
|
|
15417
|
+
refuse2("notFragmentSpan");
|
|
13988
15418
|
}
|
|
15419
|
+
const end = itemStreamEnd(raw);
|
|
13989
15420
|
return Buffer.concat([
|
|
13990
|
-
|
|
13991
|
-
|
|
13992
|
-
|
|
13993
|
-
uint16(value.length, littleEndian),
|
|
13994
|
-
value
|
|
15421
|
+
PIXEL_DATA_HEADER,
|
|
15422
|
+
raw.subarray(ELEMENT_HEADER_LENGTH2, end),
|
|
15423
|
+
SEQUENCE_DELIMITATION_ITEM
|
|
13995
15424
|
]);
|
|
13996
15425
|
}
|
|
13997
|
-
|
|
13998
|
-
// src/serialize/errors.ts
|
|
13999
|
-
var SERIALIZE_ERROR_CODES = {
|
|
14000
|
-
MISSING_TRANSFER_SYNTAX: "MISSING_TRANSFER_SYNTAX",
|
|
14001
|
-
UNSUPPORTED_TRANSFER_SYNTAX: "UNSUPPORTED_TRANSFER_SYNTAX"
|
|
14002
|
-
};
|
|
14003
|
-
var DicomSerializeError = class extends Error {
|
|
14004
|
-
code;
|
|
14005
|
-
/**
|
|
14006
|
-
* Construct a new `DicomSerializeError`. The `message` MUST be built only
|
|
14007
|
-
* from structural facts (never a decoded attribute value) so the error is
|
|
14008
|
-
* always safe to log.
|
|
14009
|
-
*
|
|
14010
|
-
* @internal
|
|
14011
|
-
*/
|
|
14012
|
-
constructor(code, message) {
|
|
14013
|
-
super(`[${code}] ${message}`);
|
|
14014
|
-
this.name = "DicomSerializeError";
|
|
14015
|
-
this.code = code;
|
|
14016
|
-
}
|
|
14017
|
-
};
|
|
14018
15426
|
var COSYTE_IMPLEMENTATION_CLASS_UID = "2.25.200853462534740285303254730069375064698";
|
|
15427
|
+
var COSYTE_IMPLEMENTATION_VERSION_NAME = "COSYTE_DICOM";
|
|
14019
15428
|
var DEFAULT_FILE_META_VERSION = Buffer.from([0, 1]);
|
|
14020
15429
|
var TAG_GROUP_LENGTH = "00020000";
|
|
14021
15430
|
function encodeMetaElement(tag, vr, rawValue) {
|
|
@@ -14087,27 +15496,54 @@ function encodeFileMeta(fileMeta) {
|
|
|
14087
15496
|
}
|
|
14088
15497
|
|
|
14089
15498
|
// src/serialize/serialize.ts
|
|
15499
|
+
var RECORD_SEQUENCE = DIRECTORY_TAGS.RECORD_SEQUENCE;
|
|
14090
15500
|
var TS_IMPLICIT_LE = "1.2.840.10008.1.2";
|
|
14091
15501
|
var TS_EXPLICIT_LE = "1.2.840.10008.1.2.1";
|
|
14092
15502
|
var TS_EXPLICIT_BE = "1.2.840.10008.1.2.2";
|
|
14093
|
-
var
|
|
15503
|
+
var TS_DEFLATED_LE2 = "1.2.840.10008.1.2.1.99";
|
|
14094
15504
|
var BODY_ENCODING = {
|
|
14095
15505
|
[TS_IMPLICIT_LE]: "implicit",
|
|
14096
15506
|
[TS_EXPLICIT_LE]: "explicitLE",
|
|
14097
15507
|
[TS_EXPLICIT_BE]: "explicitBE",
|
|
14098
15508
|
// Deflated TS body is Explicit VR LE before compression (PS3.5 Annex A.5).
|
|
14099
|
-
[
|
|
15509
|
+
[TS_DEFLATED_LE2]: "explicitLE"
|
|
14100
15510
|
};
|
|
15511
|
+
var ENCAPSULATED_SYNTAXES = new Set(ENCAPSULATED_TRANSFER_SYNTAX_UIDS);
|
|
14101
15512
|
function part10Preamble() {
|
|
14102
15513
|
return Buffer.concat([Buffer.alloc(128, 0), Buffer.from("DICM", "ascii")]);
|
|
14103
15514
|
}
|
|
14104
|
-
function encodeBody(ds, encoding) {
|
|
14105
|
-
const
|
|
14106
|
-
|
|
14107
|
-
|
|
14108
|
-
|
|
15515
|
+
function encodeBody(ds, encoding, pixelData, placed) {
|
|
15516
|
+
const kept = ds.elements().filter((el) => splitTag(el.tag).element !== 0);
|
|
15517
|
+
const closed = [];
|
|
15518
|
+
const open = [];
|
|
15519
|
+
for (const el of kept) {
|
|
15520
|
+
if (pixelData !== void 0 && el.tag === PIXEL_DATA3) {
|
|
15521
|
+
closed.push({ tag: tagNumber(el.tag), bytes: pixelData, el });
|
|
15522
|
+
continue;
|
|
15523
|
+
}
|
|
15524
|
+
const emission = emissionOf(el, encoding, placed !== void 0 && el.tag === RECORD_SEQUENCE);
|
|
15525
|
+
const bytes = encodeDatasetElement(el, encoding, emission.rawBytes);
|
|
15526
|
+
const entry = { tag: tagNumber(el.tag), bytes, el, placements: emission.placements };
|
|
15527
|
+
if (emission.closed) closed.push(entry);
|
|
15528
|
+
else open.push(entry);
|
|
14109
15529
|
}
|
|
14110
|
-
|
|
15530
|
+
closed.sort((a, b) => a.tag - b.tag);
|
|
15531
|
+
const ordered = [...closed, ...open];
|
|
15532
|
+
if (placed !== void 0) {
|
|
15533
|
+
let start = 0;
|
|
15534
|
+
for (const entry of ordered) {
|
|
15535
|
+
if (PLACED_TAGS.has(entry.el.tag)) {
|
|
15536
|
+
placed.set(entry.el.tag, {
|
|
15537
|
+
el: entry.el,
|
|
15538
|
+
start,
|
|
15539
|
+
bytes: entry.bytes,
|
|
15540
|
+
placements: entry.placements
|
|
15541
|
+
});
|
|
15542
|
+
}
|
|
15543
|
+
start += entry.bytes.length;
|
|
15544
|
+
}
|
|
15545
|
+
}
|
|
15546
|
+
return Buffer.concat(ordered.map((entry) => entry.bytes));
|
|
14111
15547
|
}
|
|
14112
15548
|
function serializeDicom(ds) {
|
|
14113
15549
|
const tsUid = ds.fileMeta?.transferSyntaxUID;
|
|
@@ -14117,18 +15553,26 @@ function serializeDicom(ds) {
|
|
|
14117
15553
|
"Dataset has no File Meta Transfer Syntax UID to serialize under."
|
|
14118
15554
|
);
|
|
14119
15555
|
}
|
|
14120
|
-
const
|
|
15556
|
+
const encapsulated = ENCAPSULATED_SYNTAXES.has(tsUid);
|
|
15557
|
+
const encoding = encapsulated ? "explicitLE" : BODY_ENCODING[tsUid];
|
|
14121
15558
|
if (encoding === void 0) {
|
|
14122
15559
|
throw new DicomSerializeError(
|
|
14123
15560
|
SERIALIZE_ERROR_CODES.UNSUPPORTED_TRANSFER_SYNTAX,
|
|
14124
|
-
`The Dataset's File Meta Transfer Syntax UID is not supported by the @cosyte/dicom
|
|
15561
|
+
`The Dataset's File Meta Transfer Syntax UID is not supported by the @cosyte/dicom writer (supported: ${Object.keys(BODY_ENCODING).join(", ")}, and every PS3.5 2026c section A.4 encapsulation syntax).`
|
|
14125
15562
|
);
|
|
14126
15563
|
}
|
|
15564
|
+
const pixelData = encapsulated ? encapsulatedPixelData(ds) : void 0;
|
|
14127
15565
|
const preamble = part10Preamble();
|
|
14128
15566
|
const fileMeta = encodeFileMeta(ds.fileMeta);
|
|
14129
|
-
const
|
|
14130
|
-
|
|
14131
|
-
|
|
15567
|
+
const deflated = tsUid === TS_DEFLATED_LE2;
|
|
15568
|
+
if (!isDicomdir(ds.fileMeta)) {
|
|
15569
|
+
const body2 = encodeBody(ds, encoding, pixelData);
|
|
15570
|
+
return Buffer.concat([preamble, fileMeta, deflated ? deflateRawSync(body2) : body2]);
|
|
15571
|
+
}
|
|
15572
|
+
const placed = /* @__PURE__ */ new Map();
|
|
15573
|
+
const body = encodeBody(ds, encoding, pixelData, placed);
|
|
15574
|
+
rewriteDirectoryOffsets(ds, body, placed, encoding, preamble.length + fileMeta.length, deflated);
|
|
15575
|
+
return Buffer.concat([preamble, fileMeta, deflated ? deflateRawSync(body) : body]);
|
|
14132
15576
|
}
|
|
14133
15577
|
|
|
14134
15578
|
// src/profiles/errors.ts
|
|
@@ -14474,26 +15918,26 @@ var ANNEX_E = Object.freeze({
|
|
|
14474
15918
|
"00001001": Object.freeze({ tag: "00001001", keyword: "Requested SOP Instance UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
|
|
14475
15919
|
"00020003": Object.freeze({ tag: "00020003", keyword: "Media Storage SOP Instance UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
|
|
14476
15920
|
"00041511": Object.freeze({ tag: "00041511", keyword: "Referenced SOP Instance UID in File", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
|
|
14477
|
-
"00080012": Object.freeze({ tag: "00080012", keyword: "Instance Creation Date", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14478
|
-
"00080013": Object.freeze({ tag: "00080013", keyword: "Instance Creation Time", basicProfile: "X/Z/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
15921
|
+
"00080012": Object.freeze({ tag: "00080012", keyword: "Instance Creation Date", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
15922
|
+
"00080013": Object.freeze({ tag: "00080013", keyword: "Instance Creation Time", basicProfile: "X/Z/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
14479
15923
|
"00080014": Object.freeze({ tag: "00080014", keyword: "Instance Creator UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
|
|
14480
|
-
"00080015": Object.freeze({ tag: "00080015", keyword: "Instance Coercion DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
15924
|
+
"00080015": Object.freeze({ tag: "00080015", keyword: "Instance Coercion DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
14481
15925
|
"00080017": Object.freeze({ tag: "00080017", keyword: "Acquisition UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
|
|
14482
15926
|
"00080018": Object.freeze({ tag: "00080018", keyword: "SOP Instance UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
|
|
14483
15927
|
"00080019": Object.freeze({ tag: "00080019", keyword: "Pyramid UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
|
|
14484
|
-
"00080020": Object.freeze({ tag: "00080020", keyword: "Study Date", basicProfile: "Z", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14485
|
-
"00080021": Object.freeze({ tag: "00080021", keyword: "Series Date", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14486
|
-
"00080022": Object.freeze({ tag: "00080022", keyword: "Acquisition Date", basicProfile: "X/Z", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14487
|
-
"00080023": Object.freeze({ tag: "00080023", keyword: "Content Date", basicProfile: "Z/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14488
|
-
"00080024": Object.freeze({ tag: "00080024", keyword: "Overlay Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14489
|
-
"00080025": Object.freeze({ tag: "00080025", keyword: "Curve Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14490
|
-
"0008002A": Object.freeze({ tag: "0008002A", keyword: "Acquisition DateTime", basicProfile: "X/Z/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14491
|
-
"00080030": Object.freeze({ tag: "00080030", keyword: "Study Time", basicProfile: "Z", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14492
|
-
"00080031": Object.freeze({ tag: "00080031", keyword: "Series Time", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14493
|
-
"00080032": Object.freeze({ tag: "00080032", keyword: "Acquisition Time", basicProfile: "X/Z", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14494
|
-
"00080033": Object.freeze({ tag: "00080033", keyword: "Content Time", basicProfile: "Z/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14495
|
-
"00080034": Object.freeze({ tag: "00080034", keyword: "Overlay Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14496
|
-
"00080035": Object.freeze({ tag: "00080035", keyword: "Curve Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
15928
|
+
"00080020": Object.freeze({ tag: "00080020", keyword: "Study Date", basicProfile: "Z", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
15929
|
+
"00080021": Object.freeze({ tag: "00080021", keyword: "Series Date", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
15930
|
+
"00080022": Object.freeze({ tag: "00080022", keyword: "Acquisition Date", basicProfile: "X/Z", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
15931
|
+
"00080023": Object.freeze({ tag: "00080023", keyword: "Content Date", basicProfile: "Z/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
15932
|
+
"00080024": Object.freeze({ tag: "00080024", keyword: "Overlay Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
15933
|
+
"00080025": Object.freeze({ tag: "00080025", keyword: "Curve Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
15934
|
+
"0008002A": Object.freeze({ tag: "0008002A", keyword: "Acquisition DateTime", basicProfile: "X/Z/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
15935
|
+
"00080030": Object.freeze({ tag: "00080030", keyword: "Study Time", basicProfile: "Z", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
15936
|
+
"00080031": Object.freeze({ tag: "00080031", keyword: "Series Time", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
15937
|
+
"00080032": Object.freeze({ tag: "00080032", keyword: "Acquisition Time", basicProfile: "X/Z", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
15938
|
+
"00080033": Object.freeze({ tag: "00080033", keyword: "Content Time", basicProfile: "Z/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
15939
|
+
"00080034": Object.freeze({ tag: "00080034", keyword: "Overlay Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
15940
|
+
"00080035": Object.freeze({ tag: "00080035", keyword: "Curve Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
14497
15941
|
"00080050": Object.freeze({ tag: "00080050", keyword: "Accession Number", basicProfile: "Z", optionSet: Object.freeze({}) }),
|
|
14498
15942
|
"00080054": Object.freeze({ tag: "00080054", keyword: "Retrieve AE Title", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "C" }) }),
|
|
14499
15943
|
"00080055": Object.freeze({ tag: "00080055", keyword: "Station AE Title", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "C" }) }),
|
|
@@ -14507,9 +15951,9 @@ var ANNEX_E = Object.freeze({
|
|
|
14507
15951
|
"00080096": Object.freeze({ tag: "00080096", keyword: "Referring Physician Identification Sequence", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
14508
15952
|
"0008009C": Object.freeze({ tag: "0008009C", keyword: "Consulting Physician's Name", basicProfile: "Z", optionSet: Object.freeze({}) }),
|
|
14509
15953
|
"0008009D": Object.freeze({ tag: "0008009D", keyword: "Consulting Physician Identification Sequence", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
14510
|
-
"00080106": Object.freeze({ tag: "00080106", keyword: "Context Group Version", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14511
|
-
"00080107": Object.freeze({ tag: "00080107", keyword: "Context Group Local Version", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14512
|
-
"00080201": Object.freeze({ tag: "00080201", keyword: "Timezone Offset From UTC", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
15954
|
+
"00080106": Object.freeze({ tag: "00080106", keyword: "Context Group Version", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
15955
|
+
"00080107": Object.freeze({ tag: "00080107", keyword: "Context Group Local Version", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
15956
|
+
"00080201": Object.freeze({ tag: "00080201", keyword: "Timezone Offset From UTC", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
14513
15957
|
"00081000": Object.freeze({ tag: "00081000", keyword: "Network ID", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "C" }) }),
|
|
14514
15958
|
"00081010": Object.freeze({ tag: "00081010", keyword: "Station Name", basicProfile: "X/Z/D", optionSet: Object.freeze({ "RetainDeviceIdentity": "K" }) }),
|
|
14515
15959
|
"00081030": Object.freeze({ tag: "00081030", keyword: "Study Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
@@ -14590,7 +16034,7 @@ var ANNEX_E = Object.freeze({
|
|
|
14590
16034
|
"001021A0": Object.freeze({ tag: "001021A0", keyword: "Smoking Status", basicProfile: "X", optionSet: Object.freeze({ "RetainPatientCharacteristics": "K" }) }),
|
|
14591
16035
|
"001021B0": Object.freeze({ tag: "001021B0", keyword: "Additional Patient History", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
14592
16036
|
"001021C0": Object.freeze({ tag: "001021C0", keyword: "Pregnancy Status", basicProfile: "X", optionSet: Object.freeze({ "RetainPatientCharacteristics": "K" }) }),
|
|
14593
|
-
"001021D0": Object.freeze({ tag: "001021D0", keyword: "Last Menstrual Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
16037
|
+
"001021D0": Object.freeze({ tag: "001021D0", keyword: "Last Menstrual Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
14594
16038
|
"001021F0": Object.freeze({ tag: "001021F0", keyword: "Patient's Religious Preference", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
14595
16039
|
"00102203": Object.freeze({ tag: "00102203", keyword: "Patient's Sex Neutered", basicProfile: "X/Z", optionSet: Object.freeze({ "RetainPatientCharacteristics": "K" }) }),
|
|
14596
16040
|
"00102297": Object.freeze({ tag: "00102297", keyword: "Responsible Person", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
@@ -14617,10 +16061,10 @@ var ANNEX_E = Object.freeze({
|
|
|
14617
16061
|
"00120073": Object.freeze({ tag: "00120073", keyword: "Issuer of Clinical Trial Series ID", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
14618
16062
|
"00120081": Object.freeze({ tag: "00120081", keyword: "Clinical Trial Protocol Ethics Committee Name", basicProfile: "D", optionSet: Object.freeze({ "RetainInstitutionIdentity": "K" }) }),
|
|
14619
16063
|
"00120082": Object.freeze({ tag: "00120082", keyword: "Clinical Trial Protocol Ethics Committee Approval Number", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
14620
|
-
"00120086": Object.freeze({ tag: "00120086", keyword: "Ethics Committee Approval Effectiveness Start Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14621
|
-
"00120087": Object.freeze({ tag: "00120087", keyword: "Ethics Committee Approval Effectiveness End Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14622
|
-
"0014407C": Object.freeze({ tag: "0014407C", keyword: "Calibration Time", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "K", "RetainLongitudinalTemporal": "K" }) }),
|
|
14623
|
-
"0014407E": Object.freeze({ tag: "0014407E", keyword: "Calibration Date", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "K", "RetainLongitudinalTemporal": "K" }) }),
|
|
16064
|
+
"00120086": Object.freeze({ tag: "00120086", keyword: "Ethics Committee Approval Effectiveness Start Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16065
|
+
"00120087": Object.freeze({ tag: "00120087", keyword: "Ethics Committee Approval Effectiveness End Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16066
|
+
"0014407C": Object.freeze({ tag: "0014407C", keyword: "Calibration Time", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "K", "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16067
|
+
"0014407E": Object.freeze({ tag: "0014407E", keyword: "Calibration Date", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "K", "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
14624
16068
|
"0016002B": Object.freeze({ tag: "0016002B", keyword: "Maker Note", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
14625
16069
|
"0016004B": Object.freeze({ tag: "0016004B", keyword: "Device Setting Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
14626
16070
|
"0016004D": Object.freeze({ tag: "0016004D", keyword: "Camera Owner Name", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
@@ -14657,11 +16101,11 @@ var ANNEX_E = Object.freeze({
|
|
|
14657
16101
|
"0016008A": Object.freeze({ tag: "0016008A", keyword: "GPS Dest Distance", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
14658
16102
|
"0016008B": Object.freeze({ tag: "0016008B", keyword: "GPS Processing Method", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
14659
16103
|
"0016008C": Object.freeze({ tag: "0016008C", keyword: "GPS Area Information", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
14660
|
-
"0016008D": Object.freeze({ tag: "0016008D", keyword: "GPS Date Stamp", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
16104
|
+
"0016008D": Object.freeze({ tag: "0016008D", keyword: "GPS Date Stamp", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
14661
16105
|
"0016008E": Object.freeze({ tag: "0016008E", keyword: "GPS Differential", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
14662
16106
|
"00180010": Object.freeze({ tag: "00180010", keyword: "Contrast/Bolus Agent", basicProfile: "Z/D", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
14663
|
-
"00180027": Object.freeze({ tag: "00180027", keyword: "Intervention Drug Stop Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14664
|
-
"00180035": Object.freeze({ tag: "00180035", keyword: "Intervention Drug Start Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
16107
|
+
"00180027": Object.freeze({ tag: "00180027", keyword: "Intervention Drug Stop Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16108
|
+
"00180035": Object.freeze({ tag: "00180035", keyword: "Intervention Drug Start Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
14665
16109
|
"00181000": Object.freeze({ tag: "00181000", keyword: "Device Serial Number", basicProfile: "X/Z/D", optionSet: Object.freeze({ "RetainDeviceIdentity": "K" }) }),
|
|
14666
16110
|
"00181002": Object.freeze({ tag: "00181002", keyword: "Device UID", basicProfile: "U", optionSet: Object.freeze({ "RetainDeviceIdentity": "K", "RetainUIDs": "K" }) }),
|
|
14667
16111
|
"00181004": Object.freeze({ tag: "00181004", keyword: "Plate ID", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "K" }) }),
|
|
@@ -14673,48 +16117,48 @@ var ANNEX_E = Object.freeze({
|
|
|
14673
16117
|
"0018100B": Object.freeze({ tag: "0018100B", keyword: "Manufacturer's Device Class UID", basicProfile: "U", optionSet: Object.freeze({ "RetainDeviceIdentity": "K", "RetainUIDs": "K" }) }),
|
|
14674
16118
|
"00181010": Object.freeze({ tag: "00181010", keyword: "Secondary Capture Device ID", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "K" }) }),
|
|
14675
16119
|
"00181011": Object.freeze({ tag: "00181011", keyword: "Hardcopy Creation Device ID", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "K" }) }),
|
|
14676
|
-
"00181012": Object.freeze({ tag: "00181012", keyword: "Date of Secondary Capture", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14677
|
-
"00181014": Object.freeze({ tag: "00181014", keyword: "Time of Secondary Capture", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
16120
|
+
"00181012": Object.freeze({ tag: "00181012", keyword: "Date of Secondary Capture", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16121
|
+
"00181014": Object.freeze({ tag: "00181014", keyword: "Time of Secondary Capture", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
14678
16122
|
"00181030": Object.freeze({ tag: "00181030", keyword: "Protocol Name", basicProfile: "X/D", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
14679
|
-
"00181042": Object.freeze({ tag: "00181042", keyword: "Contrast/Bolus Start Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14680
|
-
"00181043": Object.freeze({ tag: "00181043", keyword: "Contrast/Bolus Stop Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14681
|
-
"00181072": Object.freeze({ tag: "00181072", keyword: "Radiopharmaceutical Start Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14682
|
-
"00181073": Object.freeze({ tag: "00181073", keyword: "Radiopharmaceutical Stop Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14683
|
-
"00181078": Object.freeze({ tag: "00181078", keyword: "Radiopharmaceutical Start DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14684
|
-
"00181079": Object.freeze({ tag: "00181079", keyword: "Radiopharmaceutical Stop DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14685
|
-
"001811BB": Object.freeze({ tag: "001811BB", keyword: "Acquisition Field
|
|
14686
|
-
"00181200": Object.freeze({ tag: "00181200", keyword: "Date of Last Calibration", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "K", "RetainLongitudinalTemporal": "K" }) }),
|
|
14687
|
-
"00181201": Object.freeze({ tag: "00181201", keyword: "Time of Last Calibration", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "K", "RetainLongitudinalTemporal": "K" }) }),
|
|
14688
|
-
"00181202": Object.freeze({ tag: "00181202", keyword: "DateTime of Last Calibration", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "K", "RetainLongitudinalTemporal": "K" }) }),
|
|
14689
|
-
"00181203": Object.freeze({ tag: "00181203", keyword: "Calibration DateTime", basicProfile: "Z", optionSet: Object.freeze({ "RetainDeviceIdentity": "K", "RetainLongitudinalTemporal": "K" }) }),
|
|
14690
|
-
"00181204": Object.freeze({ tag: "00181204", keyword: "Date of Manufacture", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "K", "RetainLongitudinalTemporal": "K" }) }),
|
|
14691
|
-
"00181205": Object.freeze({ tag: "00181205", keyword: "Date of Installation", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "K", "RetainLongitudinalTemporal": "K" }) }),
|
|
16123
|
+
"00181042": Object.freeze({ tag: "00181042", keyword: "Contrast/Bolus Start Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16124
|
+
"00181043": Object.freeze({ tag: "00181043", keyword: "Contrast/Bolus Stop Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16125
|
+
"00181072": Object.freeze({ tag: "00181072", keyword: "Radiopharmaceutical Start Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16126
|
+
"00181073": Object.freeze({ tag: "00181073", keyword: "Radiopharmaceutical Stop Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16127
|
+
"00181078": Object.freeze({ tag: "00181078", keyword: "Radiopharmaceutical Start DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16128
|
+
"00181079": Object.freeze({ tag: "00181079", keyword: "Radiopharmaceutical Stop DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16129
|
+
"001811BB": Object.freeze({ tag: "001811BB", keyword: "Acquisition Field of View Label", basicProfile: "D", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
16130
|
+
"00181200": Object.freeze({ tag: "00181200", keyword: "Date of Last Calibration", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "K", "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16131
|
+
"00181201": Object.freeze({ tag: "00181201", keyword: "Time of Last Calibration", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "K", "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16132
|
+
"00181202": Object.freeze({ tag: "00181202", keyword: "DateTime of Last Calibration", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "K", "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16133
|
+
"00181203": Object.freeze({ tag: "00181203", keyword: "Calibration DateTime", basicProfile: "Z", optionSet: Object.freeze({ "RetainDeviceIdentity": "K", "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16134
|
+
"00181204": Object.freeze({ tag: "00181204", keyword: "Date of Manufacture", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "K", "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16135
|
+
"00181205": Object.freeze({ tag: "00181205", keyword: "Date of Installation", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "K", "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
14692
16136
|
"00181400": Object.freeze({ tag: "00181400", keyword: "Acquisition Device Processing Description", basicProfile: "X/D", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
14693
16137
|
"00182042": Object.freeze({ tag: "00182042", keyword: "Target UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
|
|
14694
16138
|
"00184000": Object.freeze({ tag: "00184000", keyword: "Acquisition Comments", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
14695
16139
|
"00185011": Object.freeze({ tag: "00185011", keyword: "Transducer Identification Sequence", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "K" }) }),
|
|
14696
16140
|
"0018700A": Object.freeze({ tag: "0018700A", keyword: "Detector ID", basicProfile: "X/D", optionSet: Object.freeze({ "RetainDeviceIdentity": "K" }) }),
|
|
14697
|
-
"0018700C": Object.freeze({ tag: "0018700C", keyword: "Date of Last Detector Calibration", basicProfile: "X/D", optionSet: Object.freeze({ "RetainDeviceIdentity": "K", "RetainLongitudinalTemporal": "K" }) }),
|
|
14698
|
-
"0018700E": Object.freeze({ tag: "0018700E", keyword: "Time of Last Detector Calibration", basicProfile: "X/D", optionSet: Object.freeze({ "RetainDeviceIdentity": "K", "RetainLongitudinalTemporal": "K" }) }),
|
|
14699
|
-
"00189074": Object.freeze({ tag: "00189074", keyword: "Frame Acquisition DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14700
|
-
"00189151": Object.freeze({ tag: "00189151", keyword: "Frame Reference DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
16141
|
+
"0018700C": Object.freeze({ tag: "0018700C", keyword: "Date of Last Detector Calibration", basicProfile: "X/D", optionSet: Object.freeze({ "RetainDeviceIdentity": "K", "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16142
|
+
"0018700E": Object.freeze({ tag: "0018700E", keyword: "Time of Last Detector Calibration", basicProfile: "X/D", optionSet: Object.freeze({ "RetainDeviceIdentity": "K", "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16143
|
+
"00189074": Object.freeze({ tag: "00189074", keyword: "Frame Acquisition DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16144
|
+
"00189151": Object.freeze({ tag: "00189151", keyword: "Frame Reference DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
14701
16145
|
"00189185": Object.freeze({ tag: "00189185", keyword: "Respiratory Motion Compensation Technique Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
14702
16146
|
"00189367": Object.freeze({ tag: "00189367", keyword: "X-Ray Source ID", basicProfile: "D", optionSet: Object.freeze({ "RetainDeviceIdentity": "K" }) }),
|
|
14703
|
-
"00189369": Object.freeze({ tag: "00189369", keyword: "Source Start DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14704
|
-
"0018936A": Object.freeze({ tag: "0018936A", keyword: "Source End DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
16147
|
+
"00189369": Object.freeze({ tag: "00189369", keyword: "Source Start DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16148
|
+
"0018936A": Object.freeze({ tag: "0018936A", keyword: "Source End DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
14705
16149
|
"00189371": Object.freeze({ tag: "00189371", keyword: "X-Ray Detector ID", basicProfile: "D", optionSet: Object.freeze({ "RetainDeviceIdentity": "K" }) }),
|
|
14706
16150
|
"00189373": Object.freeze({ tag: "00189373", keyword: "X-Ray Detector Label", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "K" }) }),
|
|
14707
16151
|
"0018937B": Object.freeze({ tag: "0018937B", keyword: "Multi-energy Acquisition Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
14708
16152
|
"0018937F": Object.freeze({ tag: "0018937F", keyword: "Decomposition Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
14709
16153
|
"00189424": Object.freeze({ tag: "00189424", keyword: "Acquisition Protocol Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
14710
|
-
"00189516": Object.freeze({ tag: "00189516", keyword: "Start Acquisition DateTime", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14711
|
-
"00189517": Object.freeze({ tag: "00189517", keyword: "End Acquisition DateTime", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14712
|
-
"00189623": Object.freeze({ tag: "00189623", keyword: "Functional Sync Pulse", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14713
|
-
"00189701": Object.freeze({ tag: "00189701", keyword: "Decay Correction DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14714
|
-
"00189804": Object.freeze({ tag: "00189804", keyword: "Exclusion Start DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14715
|
-
"00189919": Object.freeze({ tag: "00189919", keyword: "Instruction Performed DateTime", basicProfile: "Z/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
16154
|
+
"00189516": Object.freeze({ tag: "00189516", keyword: "Start Acquisition DateTime", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16155
|
+
"00189517": Object.freeze({ tag: "00189517", keyword: "End Acquisition DateTime", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16156
|
+
"00189623": Object.freeze({ tag: "00189623", keyword: "Functional Sync Pulse", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16157
|
+
"00189701": Object.freeze({ tag: "00189701", keyword: "Decay Correction DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16158
|
+
"00189804": Object.freeze({ tag: "00189804", keyword: "Exclusion Start DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16159
|
+
"00189919": Object.freeze({ tag: "00189919", keyword: "Instruction Performed DateTime", basicProfile: "Z/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
14716
16160
|
"00189937": Object.freeze({ tag: "00189937", keyword: "Requested Series Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
14717
|
-
"0018A002": Object.freeze({ tag: "0018A002", keyword: "Contribution DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
16161
|
+
"0018A002": Object.freeze({ tag: "0018A002", keyword: "Contribution DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
14718
16162
|
"0018A003": Object.freeze({ tag: "0018A003", keyword: "Contribution Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
14719
16163
|
"0020000D": Object.freeze({ tag: "0020000D", keyword: "Study Instance UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
|
|
14720
16164
|
"0020000E": Object.freeze({ tag: "0020000E", keyword: "Series Instance UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
|
|
@@ -14723,8 +16167,8 @@ var ANNEX_E = Object.freeze({
|
|
|
14723
16167
|
"00200052": Object.freeze({ tag: "00200052", keyword: "Frame of Reference UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
|
|
14724
16168
|
"00200200": Object.freeze({ tag: "00200200", keyword: "Synchronization Frame of Reference UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
|
|
14725
16169
|
"00203401": Object.freeze({ tag: "00203401", keyword: "Modifying Device ID", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "K" }) }),
|
|
14726
|
-
"00203403": Object.freeze({ tag: "00203403", keyword: "Modified Image Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14727
|
-
"00203405": Object.freeze({ tag: "00203405", keyword: "Modified Image Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
16170
|
+
"00203403": Object.freeze({ tag: "00203403", keyword: "Modified Image Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16171
|
+
"00203405": Object.freeze({ tag: "00203405", keyword: "Modified Image Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
14728
16172
|
"00203406": Object.freeze({ tag: "00203406", keyword: "Modified Image Description", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
14729
16173
|
"00204000": Object.freeze({ tag: "00204000", keyword: "Image Comments", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
14730
16174
|
"00209158": Object.freeze({ tag: "00209158", keyword: "Frame Comments", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
@@ -14734,23 +16178,23 @@ var ANNEX_E = Object.freeze({
|
|
|
14734
16178
|
"00281214": Object.freeze({ tag: "00281214", keyword: "Large Palette Color Lookup Table UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
|
|
14735
16179
|
"00284000": Object.freeze({ tag: "00284000", keyword: "Image Presentation Comments", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
14736
16180
|
"00320012": Object.freeze({ tag: "00320012", keyword: "Study ID Issuer", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
14737
|
-
"00320032": Object.freeze({ tag: "00320032", keyword: "Study Verified Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14738
|
-
"00320033": Object.freeze({ tag: "00320033", keyword: "Study Verified Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14739
|
-
"00320034": Object.freeze({ tag: "00320034", keyword: "Study Read Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14740
|
-
"00320035": Object.freeze({ tag: "00320035", keyword: "Study Read Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14741
|
-
"00321000": Object.freeze({ tag: "00321000", keyword: "Scheduled Study Start Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14742
|
-
"00321001": Object.freeze({ tag: "00321001", keyword: "Scheduled Study Start Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14743
|
-
"00321010": Object.freeze({ tag: "00321010", keyword: "Scheduled Study Stop Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14744
|
-
"00321011": Object.freeze({ tag: "00321011", keyword: "Scheduled Study Stop Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
16181
|
+
"00320032": Object.freeze({ tag: "00320032", keyword: "Study Verified Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16182
|
+
"00320033": Object.freeze({ tag: "00320033", keyword: "Study Verified Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16183
|
+
"00320034": Object.freeze({ tag: "00320034", keyword: "Study Read Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16184
|
+
"00320035": Object.freeze({ tag: "00320035", keyword: "Study Read Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16185
|
+
"00321000": Object.freeze({ tag: "00321000", keyword: "Scheduled Study Start Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16186
|
+
"00321001": Object.freeze({ tag: "00321001", keyword: "Scheduled Study Start Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16187
|
+
"00321010": Object.freeze({ tag: "00321010", keyword: "Scheduled Study Stop Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16188
|
+
"00321011": Object.freeze({ tag: "00321011", keyword: "Scheduled Study Stop Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
14745
16189
|
"00321020": Object.freeze({ tag: "00321020", keyword: "Scheduled Study Location", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "K" }) }),
|
|
14746
16190
|
"00321021": Object.freeze({ tag: "00321021", keyword: "Scheduled Study Location AE Title", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "C" }) }),
|
|
14747
16191
|
"00321030": Object.freeze({ tag: "00321030", keyword: "Reason for Study", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
14748
16192
|
"00321032": Object.freeze({ tag: "00321032", keyword: "Requesting Physician", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
14749
16193
|
"00321033": Object.freeze({ tag: "00321033", keyword: "Requesting Service", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
14750
|
-
"00321040": Object.freeze({ tag: "00321040", keyword: "Study Arrival Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14751
|
-
"00321041": Object.freeze({ tag: "00321041", keyword: "Study Arrival Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14752
|
-
"00321050": Object.freeze({ tag: "00321050", keyword: "Study Completion Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14753
|
-
"00321051": Object.freeze({ tag: "00321051", keyword: "Study Completion Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
16194
|
+
"00321040": Object.freeze({ tag: "00321040", keyword: "Study Arrival Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16195
|
+
"00321041": Object.freeze({ tag: "00321041", keyword: "Study Arrival Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16196
|
+
"00321050": Object.freeze({ tag: "00321050", keyword: "Study Completion Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16197
|
+
"00321051": Object.freeze({ tag: "00321051", keyword: "Study Completion Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
14754
16198
|
"00321060": Object.freeze({ tag: "00321060", keyword: "Requested Procedure Description", basicProfile: "X/Z", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
14755
16199
|
"00321066": Object.freeze({ tag: "00321066", keyword: "Reason for Visit", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
14756
16200
|
"00321067": Object.freeze({ tag: "00321067", keyword: "Reason for Visit Code Sequence", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
@@ -14759,20 +16203,20 @@ var ANNEX_E = Object.freeze({
|
|
|
14759
16203
|
"00340001": Object.freeze({ tag: "00340001", keyword: "Flow Identifier Sequence", basicProfile: "D", optionSet: Object.freeze({}) }),
|
|
14760
16204
|
"00340002": Object.freeze({ tag: "00340002", keyword: "Flow Identifier", basicProfile: "D", optionSet: Object.freeze({}) }),
|
|
14761
16205
|
"00340005": Object.freeze({ tag: "00340005", keyword: "Source Identifier", basicProfile: "D", optionSet: Object.freeze({}) }),
|
|
14762
|
-
"00340007": Object.freeze({ tag: "00340007", keyword: "Frame Origin Timestamp", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
16206
|
+
"00340007": Object.freeze({ tag: "00340007", keyword: "Frame Origin Timestamp", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
14763
16207
|
"00380004": Object.freeze({ tag: "00380004", keyword: "Referenced Patient Alias Sequence", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
14764
16208
|
"00380010": Object.freeze({ tag: "00380010", keyword: "Admission ID", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
14765
16209
|
"00380011": Object.freeze({ tag: "00380011", keyword: "Issuer of Admission ID", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
14766
16210
|
"00380014": Object.freeze({ tag: "00380014", keyword: "Issuer of Admission ID Sequence", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
14767
|
-
"0038001A": Object.freeze({ tag: "0038001A", keyword: "Scheduled Admission Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14768
|
-
"0038001B": Object.freeze({ tag: "0038001B", keyword: "Scheduled Admission Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14769
|
-
"0038001C": Object.freeze({ tag: "0038001C", keyword: "Scheduled Discharge Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14770
|
-
"0038001D": Object.freeze({ tag: "0038001D", keyword: "Scheduled Discharge Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
16211
|
+
"0038001A": Object.freeze({ tag: "0038001A", keyword: "Scheduled Admission Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16212
|
+
"0038001B": Object.freeze({ tag: "0038001B", keyword: "Scheduled Admission Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16213
|
+
"0038001C": Object.freeze({ tag: "0038001C", keyword: "Scheduled Discharge Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16214
|
+
"0038001D": Object.freeze({ tag: "0038001D", keyword: "Scheduled Discharge Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
14771
16215
|
"0038001E": Object.freeze({ tag: "0038001E", keyword: "Scheduled Patient Institution Residence", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
14772
|
-
"00380020": Object.freeze({ tag: "00380020", keyword: "Admitting Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14773
|
-
"00380021": Object.freeze({ tag: "00380021", keyword: "Admitting Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14774
|
-
"00380030": Object.freeze({ tag: "00380030", keyword: "Discharge Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14775
|
-
"00380032": Object.freeze({ tag: "00380032", keyword: "Discharge Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
16216
|
+
"00380020": Object.freeze({ tag: "00380020", keyword: "Admitting Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16217
|
+
"00380021": Object.freeze({ tag: "00380021", keyword: "Admitting Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16218
|
+
"00380030": Object.freeze({ tag: "00380030", keyword: "Discharge Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16219
|
+
"00380032": Object.freeze({ tag: "00380032", keyword: "Discharge Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
14776
16220
|
"00380040": Object.freeze({ tag: "00380040", keyword: "Discharge Diagnosis Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
14777
16221
|
"00380050": Object.freeze({ tag: "00380050", keyword: "Special Needs", basicProfile: "X", optionSet: Object.freeze({ "RetainPatientCharacteristics": "C" }) }),
|
|
14778
16222
|
"00380060": Object.freeze({ tag: "00380060", keyword: "Service Episode ID", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
@@ -14787,14 +16231,14 @@ var ANNEX_E = Object.freeze({
|
|
|
14787
16231
|
"003A0203": Object.freeze({ tag: "003A0203", keyword: "Channel Label", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
14788
16232
|
"003A020C": Object.freeze({ tag: "003A020C", keyword: "Channel Derivation Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
14789
16233
|
"003A0310": Object.freeze({ tag: "003A0310", keyword: "Multiplex Group UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
|
|
14790
|
-
"003A0314": Object.freeze({ tag: "003A0314", keyword: "Impedance Measurement DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
16234
|
+
"003A0314": Object.freeze({ tag: "003A0314", keyword: "Impedance Measurement DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
14791
16235
|
"003A0329": Object.freeze({ tag: "003A0329", keyword: "Waveform Filter Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
14792
16236
|
"003A032B": Object.freeze({ tag: "003A032B", keyword: "Filter Lookup Table Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
14793
16237
|
"00400001": Object.freeze({ tag: "00400001", keyword: "Scheduled Station AE Title", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "C" }) }),
|
|
14794
|
-
"00400002": Object.freeze({ tag: "00400002", keyword: "Scheduled Procedure Step Start Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14795
|
-
"00400003": Object.freeze({ tag: "00400003", keyword: "Scheduled Procedure Step Start Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14796
|
-
"00400004": Object.freeze({ tag: "00400004", keyword: "Scheduled Procedure Step End Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14797
|
-
"00400005": Object.freeze({ tag: "00400005", keyword: "Scheduled Procedure Step End Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
16238
|
+
"00400002": Object.freeze({ tag: "00400002", keyword: "Scheduled Procedure Step Start Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16239
|
+
"00400003": Object.freeze({ tag: "00400003", keyword: "Scheduled Procedure Step Start Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16240
|
+
"00400004": Object.freeze({ tag: "00400004", keyword: "Scheduled Procedure Step End Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16241
|
+
"00400005": Object.freeze({ tag: "00400005", keyword: "Scheduled Procedure Step End Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
14798
16242
|
"00400006": Object.freeze({ tag: "00400006", keyword: "Scheduled Performing Physician's Name", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
14799
16243
|
"00400007": Object.freeze({ tag: "00400007", keyword: "Scheduled Procedure Step Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
14800
16244
|
"00400009": Object.freeze({ tag: "00400009", keyword: "Scheduled Procedure Step ID", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
@@ -14805,10 +16249,10 @@ var ANNEX_E = Object.freeze({
|
|
|
14805
16249
|
"00400241": Object.freeze({ tag: "00400241", keyword: "Performed Station AE Title", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "C" }) }),
|
|
14806
16250
|
"00400242": Object.freeze({ tag: "00400242", keyword: "Performed Station Name", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "K" }) }),
|
|
14807
16251
|
"00400243": Object.freeze({ tag: "00400243", keyword: "Performed Location", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
14808
|
-
"00400244": Object.freeze({ tag: "00400244", keyword: "Performed Procedure Step Start Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14809
|
-
"00400245": Object.freeze({ tag: "00400245", keyword: "Performed Procedure Step Start Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14810
|
-
"00400250": Object.freeze({ tag: "00400250", keyword: "Performed Procedure Step End Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14811
|
-
"00400251": Object.freeze({ tag: "00400251", keyword: "Performed Procedure Step End Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
16252
|
+
"00400244": Object.freeze({ tag: "00400244", keyword: "Performed Procedure Step Start Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16253
|
+
"00400245": Object.freeze({ tag: "00400245", keyword: "Performed Procedure Step Start Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16254
|
+
"00400250": Object.freeze({ tag: "00400250", keyword: "Performed Procedure Step End Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16255
|
+
"00400251": Object.freeze({ tag: "00400251", keyword: "Performed Procedure Step End Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
14812
16256
|
"00400253": Object.freeze({ tag: "00400253", keyword: "Performed Procedure Step ID", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
14813
16257
|
"00400254": Object.freeze({ tag: "00400254", keyword: "Performed Procedure Step Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
14814
16258
|
"00400275": Object.freeze({ tag: "00400275", keyword: "Request Attributes Sequence", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
@@ -14840,8 +16284,8 @@ var ANNEX_E = Object.freeze({
|
|
|
14840
16284
|
"00401104": Object.freeze({ tag: "00401104", keyword: "Person's Telecom Information", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
14841
16285
|
"00401400": Object.freeze({ tag: "00401400", keyword: "Requested Procedure Comments", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
14842
16286
|
"00402001": Object.freeze({ tag: "00402001", keyword: "Reason for the Imaging Service Request", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
14843
|
-
"00402004": Object.freeze({ tag: "00402004", keyword: "Issue Date of Imaging Service Request", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14844
|
-
"00402005": Object.freeze({ tag: "00402005", keyword: "Issue Time of Imaging Service Request", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
16287
|
+
"00402004": Object.freeze({ tag: "00402004", keyword: "Issue Date of Imaging Service Request", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16288
|
+
"00402005": Object.freeze({ tag: "00402005", keyword: "Issue Time of Imaging Service Request", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
14845
16289
|
"00402008": Object.freeze({ tag: "00402008", keyword: "Order Entered By", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
14846
16290
|
"00402009": Object.freeze({ tag: "00402009", keyword: "Order Enterer's Location", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
14847
16291
|
"00402010": Object.freeze({ tag: "00402010", keyword: "Order Callback Phone Number", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
@@ -14850,10 +16294,10 @@ var ANNEX_E = Object.freeze({
|
|
|
14850
16294
|
"00402017": Object.freeze({ tag: "00402017", keyword: "Filler Order Number / Imaging Service Request", basicProfile: "Z", optionSet: Object.freeze({}) }),
|
|
14851
16295
|
"00402400": Object.freeze({ tag: "00402400", keyword: "Imaging Service Request Comments", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
14852
16296
|
"00403001": Object.freeze({ tag: "00403001", keyword: "Confidentiality Constraint on Patient Data Description", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
14853
|
-
"00404005": Object.freeze({ tag: "00404005", keyword: "Scheduled Procedure Step Start DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14854
|
-
"00404008": Object.freeze({ tag: "00404008", keyword: "Scheduled Procedure Step Expiration DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14855
|
-
"00404010": Object.freeze({ tag: "00404010", keyword: "Scheduled Procedure Step Modification DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14856
|
-
"00404011": Object.freeze({ tag: "00404011", keyword: "Expected Completion DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
16297
|
+
"00404005": Object.freeze({ tag: "00404005", keyword: "Scheduled Procedure Step Start DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16298
|
+
"00404008": Object.freeze({ tag: "00404008", keyword: "Scheduled Procedure Step Expiration DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16299
|
+
"00404010": Object.freeze({ tag: "00404010", keyword: "Scheduled Procedure Step Modification DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16300
|
+
"00404011": Object.freeze({ tag: "00404011", keyword: "Expected Completion DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
14857
16301
|
"00404023": Object.freeze({ tag: "00404023", keyword: "Referenced General Purpose Scheduled Procedure Step Transaction UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
|
|
14858
16302
|
"00404025": Object.freeze({ tag: "00404025", keyword: "Scheduled Station Name Code Sequence", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "K" }) }),
|
|
14859
16303
|
"00404027": Object.freeze({ tag: "00404027", keyword: "Scheduled Station Geographic Location Code Sequence", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "K" }) }),
|
|
@@ -14863,36 +16307,36 @@ var ANNEX_E = Object.freeze({
|
|
|
14863
16307
|
"00404035": Object.freeze({ tag: "00404035", keyword: "Actual Human Performers Sequence", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
14864
16308
|
"00404036": Object.freeze({ tag: "00404036", keyword: "Human Performer's Organization", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
14865
16309
|
"00404037": Object.freeze({ tag: "00404037", keyword: "Human Performer's Name", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
14866
|
-
"00404050": Object.freeze({ tag: "00404050", keyword: "Performed Procedure Step Start DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14867
|
-
"00404051": Object.freeze({ tag: "00404051", keyword: "Performed Procedure Step End DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14868
|
-
"00404052": Object.freeze({ tag: "00404052", keyword: "Procedure Step Cancellation DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14869
|
-
"0040A023": Object.freeze({ tag: "0040A023", keyword: "Findings Group Recording Date (Trial)", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14870
|
-
"0040A024": Object.freeze({ tag: "0040A024", keyword: "Findings Group Recording Time (Trial)", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
16310
|
+
"00404050": Object.freeze({ tag: "00404050", keyword: "Performed Procedure Step Start DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16311
|
+
"00404051": Object.freeze({ tag: "00404051", keyword: "Performed Procedure Step End DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16312
|
+
"00404052": Object.freeze({ tag: "00404052", keyword: "Procedure Step Cancellation DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16313
|
+
"0040A023": Object.freeze({ tag: "0040A023", keyword: "Findings Group Recording Date (Trial)", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16314
|
+
"0040A024": Object.freeze({ tag: "0040A024", keyword: "Findings Group Recording Time (Trial)", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
14871
16315
|
"0040A027": Object.freeze({ tag: "0040A027", keyword: "Verifying Organization", basicProfile: "D", optionSet: Object.freeze({}) }),
|
|
14872
|
-
"0040A030": Object.freeze({ tag: "0040A030", keyword: "Verification DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14873
|
-
"0040A032": Object.freeze({ tag: "0040A032", keyword: "Observation DateTime", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14874
|
-
"0040A033": Object.freeze({ tag: "0040A033", keyword: "Observation Start DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14875
|
-
"0040A034": Object.freeze({ tag: "0040A034", keyword: "Effective Start DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14876
|
-
"0040A035": Object.freeze({ tag: "0040A035", keyword: "Effective Stop DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
16316
|
+
"0040A030": Object.freeze({ tag: "0040A030", keyword: "Verification DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16317
|
+
"0040A032": Object.freeze({ tag: "0040A032", keyword: "Observation DateTime", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16318
|
+
"0040A033": Object.freeze({ tag: "0040A033", keyword: "Observation Start DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16319
|
+
"0040A034": Object.freeze({ tag: "0040A034", keyword: "Effective Start DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16320
|
+
"0040A035": Object.freeze({ tag: "0040A035", keyword: "Effective Stop DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
14877
16321
|
"0040A073": Object.freeze({ tag: "0040A073", keyword: "Verifying Observer Sequence", basicProfile: "D", optionSet: Object.freeze({}) }),
|
|
14878
16322
|
"0040A075": Object.freeze({ tag: "0040A075", keyword: "Verifying Observer Name", basicProfile: "D", optionSet: Object.freeze({}) }),
|
|
14879
16323
|
"0040A078": Object.freeze({ tag: "0040A078", keyword: "Author Observer Sequence", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
14880
16324
|
"0040A07A": Object.freeze({ tag: "0040A07A", keyword: "Participant Sequence", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
14881
16325
|
"0040A07C": Object.freeze({ tag: "0040A07C", keyword: "Custodial Organization Sequence", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
14882
|
-
"0040A082": Object.freeze({ tag: "0040A082", keyword: "Participation DateTime", basicProfile: "Z", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
16326
|
+
"0040A082": Object.freeze({ tag: "0040A082", keyword: "Participation DateTime", basicProfile: "Z", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
14883
16327
|
"0040A088": Object.freeze({ tag: "0040A088", keyword: "Verifying Observer Identification Code Sequence", basicProfile: "Z", optionSet: Object.freeze({}) }),
|
|
14884
|
-
"0040A110": Object.freeze({ tag: "0040A110", keyword: "Date of Document or Verbal Transaction (Trial)", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14885
|
-
"0040A112": Object.freeze({ tag: "0040A112", keyword: "Time of Document Creation or Verbal Transaction (Trial)", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14886
|
-
"0040A120": Object.freeze({ tag: "0040A120", keyword: "DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14887
|
-
"0040A121": Object.freeze({ tag: "0040A121", keyword: "Date", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14888
|
-
"0040A122": Object.freeze({ tag: "0040A122", keyword: "Time", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
16328
|
+
"0040A110": Object.freeze({ tag: "0040A110", keyword: "Date of Document or Verbal Transaction (Trial)", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16329
|
+
"0040A112": Object.freeze({ tag: "0040A112", keyword: "Time of Document Creation or Verbal Transaction (Trial)", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16330
|
+
"0040A120": Object.freeze({ tag: "0040A120", keyword: "DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16331
|
+
"0040A121": Object.freeze({ tag: "0040A121", keyword: "Date", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16332
|
+
"0040A122": Object.freeze({ tag: "0040A122", keyword: "Time", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
14889
16333
|
"0040A123": Object.freeze({ tag: "0040A123", keyword: "Person Name", basicProfile: "D", optionSet: Object.freeze({}) }),
|
|
14890
16334
|
"0040A124": Object.freeze({ tag: "0040A124", keyword: "UID", basicProfile: "U", optionSet: Object.freeze({}) }),
|
|
14891
|
-
"0040A13A": Object.freeze({ tag: "0040A13A", keyword: "Referenced DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
16335
|
+
"0040A13A": Object.freeze({ tag: "0040A13A", keyword: "Referenced DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
14892
16336
|
"0040A171": Object.freeze({ tag: "0040A171", keyword: "Observation UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
|
|
14893
16337
|
"0040A172": Object.freeze({ tag: "0040A172", keyword: "Referenced Observation UID (Trial)", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
|
|
14894
|
-
"0040A192": Object.freeze({ tag: "0040A192", keyword: "Observation Date (Trial)", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14895
|
-
"0040A193": Object.freeze({ tag: "0040A193", keyword: "Observation Time (Trial)", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
16338
|
+
"0040A192": Object.freeze({ tag: "0040A192", keyword: "Observation Date (Trial)", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16339
|
+
"0040A193": Object.freeze({ tag: "0040A193", keyword: "Observation Time (Trial)", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
14896
16340
|
"0040A307": Object.freeze({ tag: "0040A307", keyword: "Current Observer (Trial)", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
14897
16341
|
"0040A352": Object.freeze({ tag: "0040A352", keyword: "Verbal Source (Trial)", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
14898
16342
|
"0040A353": Object.freeze({ tag: "0040A353", keyword: "Address (Trial)", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
@@ -14901,51 +16345,51 @@ var ANNEX_E = Object.freeze({
|
|
|
14901
16345
|
"0040A402": Object.freeze({ tag: "0040A402", keyword: "Observation Subject UID (Trial)", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
|
|
14902
16346
|
"0040A730": Object.freeze({ tag: "0040A730", keyword: "Content Sequence", basicProfile: "D", optionSet: Object.freeze({ "CleanStructuredContent": "C" }) }),
|
|
14903
16347
|
"0040B020": Object.freeze({ tag: "0040B020", keyword: "Waveform Annotation Sequence", basicProfile: "X/D", optionSet: Object.freeze({ "CleanStructuredContent": "C" }) }),
|
|
14904
|
-
"0040B034": Object.freeze({ tag: "0040B034", keyword: "Annotation DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14905
|
-
"0040B036": Object.freeze({ tag: "0040B036", keyword: "Segment Definition DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
16348
|
+
"0040B034": Object.freeze({ tag: "0040B034", keyword: "Annotation DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16349
|
+
"0040B036": Object.freeze({ tag: "0040B036", keyword: "Segment Definition DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
14906
16350
|
"0040B03B": Object.freeze({ tag: "0040B03B", keyword: "Montage Name", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
14907
16351
|
"0040B03F": Object.freeze({ tag: "0040B03F", keyword: "Montage Channel Label", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
14908
|
-
"0040DB06": Object.freeze({ tag: "0040DB06", keyword: "Template Version", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14909
|
-
"0040DB07": Object.freeze({ tag: "0040DB07", keyword: "Template Local Version", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
16352
|
+
"0040DB06": Object.freeze({ tag: "0040DB06", keyword: "Template Version", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16353
|
+
"0040DB07": Object.freeze({ tag: "0040DB07", keyword: "Template Local Version", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
14910
16354
|
"0040DB0C": Object.freeze({ tag: "0040DB0C", keyword: "Template Extension Organization UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
|
|
14911
16355
|
"0040DB0D": Object.freeze({ tag: "0040DB0D", keyword: "Template Extension Creator UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
|
|
14912
|
-
"0040E004": Object.freeze({ tag: "0040E004", keyword: "HL7 Document Effective Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
16356
|
+
"0040E004": Object.freeze({ tag: "0040E004", keyword: "HL7 Document Effective Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
14913
16357
|
"0040E012": Object.freeze({ tag: "0040E012", keyword: "Display URI", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
14914
16358
|
"00420011": Object.freeze({ tag: "00420011", keyword: "Encapsulated Document", basicProfile: "D", optionSet: Object.freeze({}) }),
|
|
14915
|
-
"00440004": Object.freeze({ tag: "00440004", keyword: "Approval Status DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14916
|
-
"0044000B": Object.freeze({ tag: "0044000B", keyword: "Product Expiration DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14917
|
-
"00440010": Object.freeze({ tag: "00440010", keyword: "Substance Administration DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14918
|
-
"00440104": Object.freeze({ tag: "00440104", keyword: "Assertion DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14919
|
-
"00440105": Object.freeze({ tag: "00440105", keyword: "Assertion Expiration DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
16359
|
+
"00440004": Object.freeze({ tag: "00440004", keyword: "Approval Status DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16360
|
+
"0044000B": Object.freeze({ tag: "0044000B", keyword: "Product Expiration DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16361
|
+
"00440010": Object.freeze({ tag: "00440010", keyword: "Substance Administration DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16362
|
+
"00440104": Object.freeze({ tag: "00440104", keyword: "Assertion DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16363
|
+
"00440105": Object.freeze({ tag: "00440105", keyword: "Assertion Expiration DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
14920
16364
|
"0050001B": Object.freeze({ tag: "0050001B", keyword: "Container Component ID", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
14921
16365
|
"00500020": Object.freeze({ tag: "00500020", keyword: "Device Description", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "K" }) }),
|
|
14922
16366
|
"00500021": Object.freeze({ tag: "00500021", keyword: "Long Device Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
14923
16367
|
"00620021": Object.freeze({ tag: "00620021", keyword: "Tracking UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
|
|
14924
16368
|
"00640003": Object.freeze({ tag: "00640003", keyword: "Source Frame of Reference UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
|
|
14925
|
-
"00686226": Object.freeze({ tag: "00686226", keyword: "Effective DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14926
|
-
"00686270": Object.freeze({ tag: "00686270", keyword: "Information Issue DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
16369
|
+
"00686226": Object.freeze({ tag: "00686226", keyword: "Effective DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16370
|
+
"00686270": Object.freeze({ tag: "00686270", keyword: "Information Issue DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
14927
16371
|
"006A0003": Object.freeze({ tag: "006A0003", keyword: "Annotation Group UID", basicProfile: "D", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
|
|
14928
16372
|
"006A0005": Object.freeze({ tag: "006A0005", keyword: "Annotation Group Label", basicProfile: "D", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
14929
16373
|
"006A0006": Object.freeze({ tag: "006A0006", keyword: "Annotation Group Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
14930
16374
|
"00700001": Object.freeze({ tag: "00700001", keyword: "Graphic Annotation Sequence", basicProfile: "D", optionSet: Object.freeze({ "CleanGraphics": "C" }) }),
|
|
14931
16375
|
"00700006": Object.freeze({ tag: "00700006", keyword: "Unformatted Text Value", basicProfile: "D", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
14932
|
-
"00700082": Object.freeze({ tag: "00700082", keyword: "Presentation Creation Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14933
|
-
"00700083": Object.freeze({ tag: "00700083", keyword: "Presentation Creation Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
16376
|
+
"00700082": Object.freeze({ tag: "00700082", keyword: "Presentation Creation Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16377
|
+
"00700083": Object.freeze({ tag: "00700083", keyword: "Presentation Creation Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
14934
16378
|
"00700084": Object.freeze({ tag: "00700084", keyword: "Content Creator's Name", basicProfile: "Z/D", optionSet: Object.freeze({}) }),
|
|
14935
16379
|
"00700086": Object.freeze({ tag: "00700086", keyword: "Content Creator's Identification Code Sequence", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
14936
16380
|
"0070031A": Object.freeze({ tag: "0070031A", keyword: "Fiducial UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
|
|
14937
16381
|
"00701101": Object.freeze({ tag: "00701101", keyword: "Presentation Display Collection UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
|
|
14938
16382
|
"00701102": Object.freeze({ tag: "00701102", keyword: "Presentation Sequence Collection UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
|
|
14939
|
-
"0072000A": Object.freeze({ tag: "0072000A", keyword: "Hanging Protocol Creation DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
16383
|
+
"0072000A": Object.freeze({ tag: "0072000A", keyword: "Hanging Protocol Creation DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
14940
16384
|
"0072005E": Object.freeze({ tag: "0072005E", keyword: "Selector AE Value", basicProfile: "D", optionSet: Object.freeze({ "RetainDeviceIdentity": "C" }) }),
|
|
14941
16385
|
"0072005F": Object.freeze({ tag: "0072005F", keyword: "Selector AS Value", basicProfile: "D", optionSet: Object.freeze({ "RetainPatientCharacteristics": "K" }) }),
|
|
14942
|
-
"00720061": Object.freeze({ tag: "00720061", keyword: "Selector DA Value", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14943
|
-
"00720063": Object.freeze({ tag: "00720063", keyword: "Selector DT Value", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
16386
|
+
"00720061": Object.freeze({ tag: "00720061", keyword: "Selector DA Value", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16387
|
+
"00720063": Object.freeze({ tag: "00720063", keyword: "Selector DT Value", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
14944
16388
|
"00720065": Object.freeze({ tag: "00720065", keyword: "Selector OB Value", basicProfile: "D", optionSet: Object.freeze({}) }),
|
|
14945
16389
|
"00720066": Object.freeze({ tag: "00720066", keyword: "Selector LO Value", basicProfile: "D", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
14946
16390
|
"00720068": Object.freeze({ tag: "00720068", keyword: "Selector LT Value", basicProfile: "D", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
14947
16391
|
"0072006A": Object.freeze({ tag: "0072006A", keyword: "Selector PN Value", basicProfile: "D", optionSet: Object.freeze({}) }),
|
|
14948
|
-
"0072006B": Object.freeze({ tag: "0072006B", keyword: "Selector TM Value", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
16392
|
+
"0072006B": Object.freeze({ tag: "0072006B", keyword: "Selector TM Value", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
14949
16393
|
"0072006C": Object.freeze({ tag: "0072006C", keyword: "Selector SH Value", basicProfile: "D", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
14950
16394
|
"0072006D": Object.freeze({ tag: "0072006D", keyword: "Selector UN Value", basicProfile: "D", optionSet: Object.freeze({}) }),
|
|
14951
16395
|
"0072006E": Object.freeze({ tag: "0072006E", keyword: "Selector ST Value", basicProfile: "D", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
@@ -14959,11 +16403,11 @@ var ANNEX_E = Object.freeze({
|
|
|
14959
16403
|
"00880906": Object.freeze({ tag: "00880906", keyword: "Topic Subject", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
14960
16404
|
"00880910": Object.freeze({ tag: "00880910", keyword: "Topic Author", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
14961
16405
|
"00880912": Object.freeze({ tag: "00880912", keyword: "Topic Keywords", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
14962
|
-
"01000420": Object.freeze({ tag: "01000420", keyword: "SOP Authorization DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
16406
|
+
"01000420": Object.freeze({ tag: "01000420", keyword: "SOP Authorization DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
14963
16407
|
"04000100": Object.freeze({ tag: "04000100", keyword: "Digital Signature UID", basicProfile: "U", optionSet: Object.freeze({}) }),
|
|
14964
|
-
"04000105": Object.freeze({ tag: "04000105", keyword: "Digital Signature DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
16408
|
+
"04000105": Object.freeze({ tag: "04000105", keyword: "Digital Signature DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
14965
16409
|
"04000115": Object.freeze({ tag: "04000115", keyword: "Certificate of Signer", basicProfile: "D", optionSet: Object.freeze({}) }),
|
|
14966
|
-
"04000310": Object.freeze({ tag: "04000310", keyword: "Certified Timestamp", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
16410
|
+
"04000310": Object.freeze({ tag: "04000310", keyword: "Certified Timestamp", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
14967
16411
|
"04000402": Object.freeze({ tag: "04000402", keyword: "Referenced Digital Signature Sequence", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
14968
16412
|
"04000403": Object.freeze({ tag: "04000403", keyword: "Referenced SOP Instance MAC Sequence", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
14969
16413
|
"04000404": Object.freeze({ tag: "04000404", keyword: "MAC", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
@@ -14971,30 +16415,31 @@ var ANNEX_E = Object.freeze({
|
|
|
14971
16415
|
"04000551": Object.freeze({ tag: "04000551", keyword: "Nonconforming Modified Attributes Sequence", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
14972
16416
|
"04000552": Object.freeze({ tag: "04000552", keyword: "Nonconforming Data Element Value", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
14973
16417
|
"04000561": Object.freeze({ tag: "04000561", keyword: "Original Attributes Sequence", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
14974
|
-
"04000562": Object.freeze({ tag: "04000562", keyword: "Attribute Modification DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
16418
|
+
"04000562": Object.freeze({ tag: "04000562", keyword: "Attribute Modification DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
14975
16419
|
"04000563": Object.freeze({ tag: "04000563", keyword: "Modifying System", basicProfile: "D", optionSet: Object.freeze({ "RetainDeviceIdentity": "K" }) }),
|
|
14976
16420
|
"04000564": Object.freeze({ tag: "04000564", keyword: "Source of Previous Values", basicProfile: "Z", optionSet: Object.freeze({ "RetainInstitutionIdentity": "K" }) }),
|
|
14977
16421
|
"04000565": Object.freeze({ tag: "04000565", keyword: "Reason for the Attribute Modification", basicProfile: "D", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
14978
16422
|
"04000600": Object.freeze({ tag: "04000600", keyword: "Instance Origin Status", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
14979
16423
|
"20300020": Object.freeze({ tag: "20300020", keyword: "Text String", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
14980
|
-
"21000040": Object.freeze({ tag: "21000040", keyword: "Creation Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14981
|
-
"21000050": Object.freeze({ tag: "21000050", keyword: "Creation Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
16424
|
+
"21000040": Object.freeze({ tag: "21000040", keyword: "Creation Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16425
|
+
"21000050": Object.freeze({ tag: "21000050", keyword: "Creation Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
14982
16426
|
"21000070": Object.freeze({ tag: "21000070", keyword: "Originator", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "C" }) }),
|
|
14983
16427
|
"21000140": Object.freeze({ tag: "21000140", keyword: "Destination AE", basicProfile: "D", optionSet: Object.freeze({ "RetainDeviceIdentity": "C" }) }),
|
|
14984
16428
|
"22000002": Object.freeze({ tag: "22000002", keyword: "Label Text", basicProfile: "X/Z", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
14985
16429
|
"22000005": Object.freeze({ tag: "22000005", keyword: "Barcode Value", basicProfile: "X/Z", optionSet: Object.freeze({}) }),
|
|
14986
16430
|
"30020121": Object.freeze({ tag: "30020121", keyword: "Position Acquisition Template Name", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
14987
16431
|
"30020123": Object.freeze({ tag: "30020123", keyword: "Position Acquisition Template Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
16432
|
+
"3004007F": Object.freeze({ tag: "3004007F", keyword: "Dose Calculation Model Name", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
14988
16433
|
"30060002": Object.freeze({ tag: "30060002", keyword: "Structure Set Label", basicProfile: "D", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
14989
16434
|
"30060004": Object.freeze({ tag: "30060004", keyword: "Structure Set Name", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
14990
16435
|
"30060006": Object.freeze({ tag: "30060006", keyword: "Structure Set Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
14991
|
-
"30060008": Object.freeze({ tag: "30060008", keyword: "Structure Set Date", basicProfile: "Z", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14992
|
-
"30060009": Object.freeze({ tag: "30060009", keyword: "Structure Set Time", basicProfile: "Z", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
16436
|
+
"30060008": Object.freeze({ tag: "30060008", keyword: "Structure Set Date", basicProfile: "Z", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16437
|
+
"30060009": Object.freeze({ tag: "30060009", keyword: "Structure Set Time", basicProfile: "Z", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
14993
16438
|
"30060024": Object.freeze({ tag: "30060024", keyword: "Referenced Frame of Reference UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
|
|
14994
16439
|
"30060026": Object.freeze({ tag: "30060026", keyword: "ROI Name", basicProfile: "Z", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
14995
16440
|
"30060028": Object.freeze({ tag: "30060028", keyword: "ROI Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
14996
|
-
"3006002D": Object.freeze({ tag: "3006002D", keyword: "ROI DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
14997
|
-
"3006002E": Object.freeze({ tag: "3006002E", keyword: "ROI Observation DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
16441
|
+
"3006002D": Object.freeze({ tag: "3006002D", keyword: "ROI DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16442
|
+
"3006002E": Object.freeze({ tag: "3006002E", keyword: "ROI Observation DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
14998
16443
|
"30060038": Object.freeze({ tag: "30060038", keyword: "ROI Generation Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
14999
16444
|
"3006004D": Object.freeze({ tag: "3006004D", keyword: "ROI Creator Sequence", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
15000
16445
|
"3006004E": Object.freeze({ tag: "3006004E", keyword: "ROI Interpreter Sequence", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
@@ -15002,22 +16447,22 @@ var ANNEX_E = Object.freeze({
|
|
|
15002
16447
|
"30060088": Object.freeze({ tag: "30060088", keyword: "ROI Observation Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
15003
16448
|
"300600A6": Object.freeze({ tag: "300600A6", keyword: "ROI Interpreter", basicProfile: "Z", optionSet: Object.freeze({}) }),
|
|
15004
16449
|
"300600C2": Object.freeze({ tag: "300600C2", keyword: "Related Frame of Reference UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
|
|
15005
|
-
"30080024": Object.freeze({ tag: "30080024", keyword: "Treatment Control Point Date", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
15006
|
-
"30080025": Object.freeze({ tag: "30080025", keyword: "Treatment Control Point Time", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
15007
|
-
"30080054": Object.freeze({ tag: "30080054", keyword: "First Treatment Date", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
15008
|
-
"30080056": Object.freeze({ tag: "30080056", keyword: "Most Recent Treatment Date", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
16450
|
+
"30080024": Object.freeze({ tag: "30080024", keyword: "Treatment Control Point Date", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16451
|
+
"30080025": Object.freeze({ tag: "30080025", keyword: "Treatment Control Point Time", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16452
|
+
"30080054": Object.freeze({ tag: "30080054", keyword: "First Treatment Date", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16453
|
+
"30080056": Object.freeze({ tag: "30080056", keyword: "Most Recent Treatment Date", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
15009
16454
|
"30080105": Object.freeze({ tag: "30080105", keyword: "Source Serial Number", basicProfile: "X/Z", optionSet: Object.freeze({ "RetainDeviceIdentity": "K" }) }),
|
|
15010
|
-
"30080162": Object.freeze({ tag: "30080162", keyword: "Safe Position Exit Date", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
15011
|
-
"30080164": Object.freeze({ tag: "30080164", keyword: "Safe Position Exit Time", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
15012
|
-
"30080166": Object.freeze({ tag: "30080166", keyword: "Safe Position Return Date", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
15013
|
-
"30080168": Object.freeze({ tag: "30080168", keyword: "Safe Position Return Time", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
15014
|
-
"30080250": Object.freeze({ tag: "30080250", keyword: "Treatment Date", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
15015
|
-
"30080251": Object.freeze({ tag: "30080251", keyword: "Treatment Time", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
16455
|
+
"30080162": Object.freeze({ tag: "30080162", keyword: "Safe Position Exit Date", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16456
|
+
"30080164": Object.freeze({ tag: "30080164", keyword: "Safe Position Exit Time", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16457
|
+
"30080166": Object.freeze({ tag: "30080166", keyword: "Safe Position Return Date", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16458
|
+
"30080168": Object.freeze({ tag: "30080168", keyword: "Safe Position Return Time", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16459
|
+
"30080250": Object.freeze({ tag: "30080250", keyword: "Treatment Date", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16460
|
+
"30080251": Object.freeze({ tag: "30080251", keyword: "Treatment Time", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
15016
16461
|
"300A0002": Object.freeze({ tag: "300A0002", keyword: "RT Plan Label", basicProfile: "D", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
15017
16462
|
"300A0003": Object.freeze({ tag: "300A0003", keyword: "RT Plan Name", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
15018
16463
|
"300A0004": Object.freeze({ tag: "300A0004", keyword: "RT Plan Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
15019
|
-
"300A0006": Object.freeze({ tag: "300A0006", keyword: "RT Plan Date", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
15020
|
-
"300A0007": Object.freeze({ tag: "300A0007", keyword: "RT Plan Time", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
16464
|
+
"300A0006": Object.freeze({ tag: "300A0006", keyword: "RT Plan Date", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16465
|
+
"300A0007": Object.freeze({ tag: "300A0007", keyword: "RT Plan Time", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
15021
16466
|
"300A000B": Object.freeze({ tag: "300A000B", keyword: "Treatment Sites", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
15022
16467
|
"300A000E": Object.freeze({ tag: "300A000E", keyword: "Prescription Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
15023
16468
|
"300A0013": Object.freeze({ tag: "300A0013", keyword: "Dose Reference UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
|
|
@@ -15032,8 +16477,8 @@ var ANNEX_E = Object.freeze({
|
|
|
15032
16477
|
"300A01A6": Object.freeze({ tag: "300A01A6", keyword: "Shielding Device Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
15033
16478
|
"300A01B2": Object.freeze({ tag: "300A01B2", keyword: "Setup Technique Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
15034
16479
|
"300A0216": Object.freeze({ tag: "300A0216", keyword: "Source Manufacturer", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "K" }) }),
|
|
15035
|
-
"300A022C": Object.freeze({ tag: "300A022C", keyword: "Source Strength Reference Date", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
15036
|
-
"300A022E": Object.freeze({ tag: "300A022E", keyword: "Source Strength Reference Time", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
16480
|
+
"300A022C": Object.freeze({ tag: "300A022C", keyword: "Source Strength Reference Date", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16481
|
+
"300A022E": Object.freeze({ tag: "300A022E", keyword: "Source Strength Reference Time", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
15037
16482
|
"300A02EB": Object.freeze({ tag: "300A02EB", keyword: "Compensator Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
15038
16483
|
"300A0608": Object.freeze({ tag: "300A0608", keyword: "Treatment Position Group Label", basicProfile: "D", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
15039
16484
|
"300A0609": Object.freeze({ tag: "300A0609", keyword: "Treatment Position Group UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
|
|
@@ -15048,11 +16493,11 @@ var ANNEX_E = Object.freeze({
|
|
|
15048
16493
|
"300A067D": Object.freeze({ tag: "300A067D", keyword: "Radiation Generation Mode Description", basicProfile: "Z", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
15049
16494
|
"300A0700": Object.freeze({ tag: "300A0700", keyword: "Treatment Session UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
|
|
15050
16495
|
"300A0734": Object.freeze({ tag: "300A0734", keyword: "Treatment Tolerance Violation Description", basicProfile: "D", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
15051
|
-
"300A0736": Object.freeze({ tag: "300A0736", keyword: "Treatment Tolerance Violation DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
15052
|
-
"300A073A": Object.freeze({ tag: "300A073A", keyword: "Recorded RT Control Point DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
15053
|
-
"300A0741": Object.freeze({ tag: "300A0741", keyword: "Interlock DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
16496
|
+
"300A0736": Object.freeze({ tag: "300A0736", keyword: "Treatment Tolerance Violation DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16497
|
+
"300A073A": Object.freeze({ tag: "300A073A", keyword: "Recorded RT Control Point DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16498
|
+
"300A0741": Object.freeze({ tag: "300A0741", keyword: "Interlock DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
15054
16499
|
"300A0742": Object.freeze({ tag: "300A0742", keyword: "Interlock Description", basicProfile: "D", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
15055
|
-
"300A0760": Object.freeze({ tag: "300A0760", keyword: "Override DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
16500
|
+
"300A0760": Object.freeze({ tag: "300A0760", keyword: "Override DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
15056
16501
|
"300A0783": Object.freeze({ tag: "300A0783", keyword: "Interlock Origin Description", basicProfile: "D", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
15057
16502
|
"300A0785": Object.freeze({ tag: "300A0785", keyword: "Referenced Treatment Position Group UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
|
|
15058
16503
|
"300A078E": Object.freeze({ tag: "300A078E", keyword: "Patient Treatment Preparation Procedure Parameter Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
@@ -15060,9 +16505,9 @@ var ANNEX_E = Object.freeze({
|
|
|
15060
16505
|
"300A0794": Object.freeze({ tag: "300A0794", keyword: "Patient Setup Photo Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
15061
16506
|
"300A079A": Object.freeze({ tag: "300A079A", keyword: "Displacement Reference Label", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
15062
16507
|
"300C0113": Object.freeze({ tag: "300C0113", keyword: "Reason for Omission Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
15063
|
-
"300C0127": Object.freeze({ tag: "300C0127", keyword: "Beam Hold Transition DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainDeviceIdentity": "K", "RetainLongitudinalTemporal": "K" }) }),
|
|
15064
|
-
"300E0004": Object.freeze({ tag: "300E0004", keyword: "Review Date", basicProfile: "Z", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
15065
|
-
"300E0005": Object.freeze({ tag: "300E0005", keyword: "Review Time", basicProfile: "Z", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
16508
|
+
"300C0127": Object.freeze({ tag: "300C0127", keyword: "Beam Hold Transition DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainDeviceIdentity": "K", "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16509
|
+
"300E0004": Object.freeze({ tag: "300E0004", keyword: "Review Date", basicProfile: "Z", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16510
|
+
"300E0005": Object.freeze({ tag: "300E0005", keyword: "Review Time", basicProfile: "Z", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
15066
16511
|
"300E0008": Object.freeze({ tag: "300E0008", keyword: "Reviewer Name", basicProfile: "X/Z", optionSet: Object.freeze({}) }),
|
|
15067
16512
|
"30100006": Object.freeze({ tag: "30100006", keyword: "Conceptual Volume UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
|
|
15068
16513
|
"3010000B": Object.freeze({ tag: "3010000B", keyword: "Referenced Conceptual Volume UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
|
|
@@ -15081,8 +16526,8 @@ var ANNEX_E = Object.freeze({
|
|
|
15081
16526
|
"30100038": Object.freeze({ tag: "30100038", keyword: "Entity Long Label", basicProfile: "D", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
15082
16527
|
"3010003B": Object.freeze({ tag: "3010003B", keyword: "RT Treatment Phase UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
|
|
15083
16528
|
"30100043": Object.freeze({ tag: "30100043", keyword: "Manufacturer's Device Identifier", basicProfile: "Z", optionSet: Object.freeze({ "RetainDeviceIdentity": "K" }) }),
|
|
15084
|
-
"3010004C": Object.freeze({ tag: "3010004C", keyword: "Intended Phase Start Date", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
15085
|
-
"3010004D": Object.freeze({ tag: "3010004D", keyword: "Intended Phase End Date", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
16529
|
+
"3010004C": Object.freeze({ tag: "3010004C", keyword: "Intended Phase Start Date", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16530
|
+
"3010004D": Object.freeze({ tag: "3010004D", keyword: "Intended Phase End Date", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
15086
16531
|
"30100054": Object.freeze({ tag: "30100054", keyword: "RT Prescription Label", basicProfile: "D", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
15087
16532
|
"30100056": Object.freeze({ tag: "30100056", keyword: "RT Treatment Approach Label", basicProfile: "X/D", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
15088
16533
|
"3010005A": Object.freeze({ tag: "3010005A", keyword: "RT Physician Intent Narrative", basicProfile: "Z", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
@@ -15095,22 +16540,22 @@ var ANNEX_E = Object.freeze({
|
|
|
15095
16540
|
"3010007B": Object.freeze({ tag: "3010007B", keyword: "Prescription Notes", basicProfile: "Z", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
15096
16541
|
"3010007F": Object.freeze({ tag: "3010007F", keyword: "Fractionation Notes", basicProfile: "Z", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
15097
16542
|
"30100081": Object.freeze({ tag: "30100081", keyword: "Prescription Notes Sequence", basicProfile: "Z", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
15098
|
-
"30100085": Object.freeze({ tag: "30100085", keyword: "Intended Fraction Start Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
16543
|
+
"30100085": Object.freeze({ tag: "30100085", keyword: "Intended Fraction Start Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
15099
16544
|
"40000010": Object.freeze({ tag: "40000010", keyword: "Arbitrary", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
15100
16545
|
"40004000": Object.freeze({ tag: "40004000", keyword: "Text Comments", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
15101
16546
|
"40080040": Object.freeze({ tag: "40080040", keyword: "Results ID", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
15102
16547
|
"40080042": Object.freeze({ tag: "40080042", keyword: "Results ID Issuer", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
15103
|
-
"40080100": Object.freeze({ tag: "40080100", keyword: "Interpretation Recorded Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
15104
|
-
"40080101": Object.freeze({ tag: "40080101", keyword: "Interpretation Recorded Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
16548
|
+
"40080100": Object.freeze({ tag: "40080100", keyword: "Interpretation Recorded Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16549
|
+
"40080101": Object.freeze({ tag: "40080101", keyword: "Interpretation Recorded Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
15105
16550
|
"40080102": Object.freeze({ tag: "40080102", keyword: "Interpretation Recorder", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
15106
|
-
"40080108": Object.freeze({ tag: "40080108", keyword: "Interpretation Transcription Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
15107
|
-
"40080109": Object.freeze({ tag: "40080109", keyword: "Interpretation Transcription Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
16551
|
+
"40080108": Object.freeze({ tag: "40080108", keyword: "Interpretation Transcription Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16552
|
+
"40080109": Object.freeze({ tag: "40080109", keyword: "Interpretation Transcription Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
15108
16553
|
"4008010A": Object.freeze({ tag: "4008010A", keyword: "Interpretation Transcriber", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
15109
16554
|
"4008010B": Object.freeze({ tag: "4008010B", keyword: "Interpretation Text", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
15110
16555
|
"4008010C": Object.freeze({ tag: "4008010C", keyword: "Interpretation Author", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
15111
16556
|
"40080111": Object.freeze({ tag: "40080111", keyword: "Interpretation Approver Sequence", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
15112
|
-
"40080112": Object.freeze({ tag: "40080112", keyword: "Interpretation Approval Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
15113
|
-
"40080113": Object.freeze({ tag: "40080113", keyword: "Interpretation Approval Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
|
|
16557
|
+
"40080112": Object.freeze({ tag: "40080112", keyword: "Interpretation Approval Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
16558
|
+
"40080113": Object.freeze({ tag: "40080113", keyword: "Interpretation Approval Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
|
|
15114
16559
|
"40080114": Object.freeze({ tag: "40080114", keyword: "Physician Approving Interpretation", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
15115
16560
|
"40080115": Object.freeze({ tag: "40080115", keyword: "Interpretation Diagnosis Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
|
|
15116
16561
|
"40080118": Object.freeze({ tag: "40080118", keyword: "Results Distribution List Sequence", basicProfile: "X", optionSet: Object.freeze({}) }),
|
|
@@ -15180,6 +16625,73 @@ function matchRepeatingRule(upper) {
|
|
|
15180
16625
|
}
|
|
15181
16626
|
return void 0;
|
|
15182
16627
|
}
|
|
16628
|
+
|
|
16629
|
+
// src/dictionary/registered.ts
|
|
16630
|
+
var CONCRETE_TAG_RE = /^[0-9A-F]{8}$/;
|
|
16631
|
+
var MASK_CHAR = "x";
|
|
16632
|
+
var MASKED_ROWS = Object.freeze(
|
|
16633
|
+
Object.keys(TAGS).filter((key) => key.includes(MASK_CHAR))
|
|
16634
|
+
);
|
|
16635
|
+
function isSection76Family(pattern) {
|
|
16636
|
+
return REPEATING_GROUP_RANGES[pattern.slice(0, 2).toUpperCase()] !== void 0 && pattern.slice(2, 4) === MASK_CHAR + MASK_CHAR;
|
|
16637
|
+
}
|
|
16638
|
+
function matchesMaskedRow(pattern, tag) {
|
|
16639
|
+
if (isSection76Family(pattern)) return matchesRepeatingPattern(pattern, tag);
|
|
16640
|
+
for (let i = 0; i < pattern.length; i++) {
|
|
16641
|
+
const printed = pattern.charAt(i);
|
|
16642
|
+
if (printed === MASK_CHAR) continue;
|
|
16643
|
+
if (printed.toUpperCase() !== tag.charAt(i)) return false;
|
|
16644
|
+
}
|
|
16645
|
+
return true;
|
|
16646
|
+
}
|
|
16647
|
+
function isRegisteredTag(tag) {
|
|
16648
|
+
if (typeof tag !== "string") return false;
|
|
16649
|
+
const upper = tag.toUpperCase();
|
|
16650
|
+
if (!CONCRETE_TAG_RE.test(upper)) return false;
|
|
16651
|
+
if (Object.prototype.hasOwnProperty.call(TAGS, upper)) return true;
|
|
16652
|
+
return MASKED_ROWS.some((pattern) => matchesMaskedRow(pattern, upper));
|
|
16653
|
+
}
|
|
16654
|
+
|
|
16655
|
+
// src/deident/types.ts
|
|
16656
|
+
var DEIDENTIFY_OPTIONS = Object.freeze([
|
|
16657
|
+
"CleanGraphics",
|
|
16658
|
+
"CleanStructuredContent",
|
|
16659
|
+
"CleanDescriptors",
|
|
16660
|
+
"RetainLongitudinalTemporal",
|
|
16661
|
+
"RetainLongitudinalTemporalModifiedDates",
|
|
16662
|
+
"RetainPatientCharacteristics",
|
|
16663
|
+
"RetainDeviceIdentity",
|
|
16664
|
+
"RetainUIDs",
|
|
16665
|
+
"RetainSafePrivate",
|
|
16666
|
+
"RetainInstitutionIdentity"
|
|
16667
|
+
]);
|
|
16668
|
+
var DEIDENTIFY_ERROR_CODES = Object.freeze({
|
|
16669
|
+
INVALID_OPTIONS: "INVALID_OPTIONS",
|
|
16670
|
+
UNSUPPORTED_TRANSFER_SYNTAX: "UNSUPPORTED_TRANSFER_SYNTAX"
|
|
16671
|
+
});
|
|
16672
|
+
var DeidentifyError = class extends Error {
|
|
16673
|
+
code;
|
|
16674
|
+
/**
|
|
16675
|
+
* @param message Human-readable, PHI-free description.
|
|
16676
|
+
* @param code One of {@link DEIDENTIFY_ERROR_CODES}.
|
|
16677
|
+
*/
|
|
16678
|
+
constructor(message, code) {
|
|
16679
|
+
super(message);
|
|
16680
|
+
this.name = "DeidentifyError";
|
|
16681
|
+
this.code = code;
|
|
16682
|
+
}
|
|
16683
|
+
};
|
|
16684
|
+
|
|
16685
|
+
// src/deident/actions.ts
|
|
16686
|
+
function effectiveCode(action, active) {
|
|
16687
|
+
for (const opt of DEIDENTIFY_OPTIONS) {
|
|
16688
|
+
if (active.has(opt)) {
|
|
16689
|
+
const override = action.optionSet[opt];
|
|
16690
|
+
if (override !== void 0) return override;
|
|
16691
|
+
}
|
|
16692
|
+
}
|
|
16693
|
+
return action.basicProfile;
|
|
16694
|
+
}
|
|
15183
16695
|
function resolveAction(code) {
|
|
15184
16696
|
const first = code.split("/", 1)[0]?.replace("*", "") ?? "K";
|
|
15185
16697
|
return first;
|
|
@@ -15221,7 +16733,7 @@ function uidValueMultiplicity(rawBytes) {
|
|
|
15221
16733
|
}
|
|
15222
16734
|
|
|
15223
16735
|
// src/deident/embedded.ts
|
|
15224
|
-
var
|
|
16736
|
+
var UNDEFINED_LENGTH7 = 4294967295;
|
|
15225
16737
|
var FFFE_GROUP = 65534;
|
|
15226
16738
|
var SCANNABLE_CARRIER_VRS = /* @__PURE__ */ new Set([
|
|
15227
16739
|
"AE",
|
|
@@ -15276,7 +16788,7 @@ function decodeAt(value, off, encoding) {
|
|
|
15276
16788
|
const tag = joinTag(group, element);
|
|
15277
16789
|
if (encoding === "implicit") {
|
|
15278
16790
|
const length2 = readU32(value, off + 4, littleEndian);
|
|
15279
|
-
if (length2 ===
|
|
16791
|
+
if (length2 === UNDEFINED_LENGTH7 || length2 % 2 !== 0) return void 0;
|
|
15280
16792
|
const next2 = off + 8 + length2;
|
|
15281
16793
|
return next2 > value.length ? void 0 : { next: next2, tag };
|
|
15282
16794
|
}
|
|
@@ -15286,7 +16798,7 @@ function decodeAt(value, off, encoding) {
|
|
|
15286
16798
|
if (off + 12 > value.length) return void 0;
|
|
15287
16799
|
if (value[off + 6] !== 0 || value[off + 7] !== 0) return void 0;
|
|
15288
16800
|
const length2 = readU32(value, off + 8, littleEndian);
|
|
15289
|
-
if (length2 ===
|
|
16801
|
+
if (length2 === UNDEFINED_LENGTH7 || length2 % 2 !== 0) return void 0;
|
|
15290
16802
|
const next2 = off + 12 + length2;
|
|
15291
16803
|
return next2 > value.length ? void 0 : { next: next2, tag };
|
|
15292
16804
|
}
|
|
@@ -15353,33 +16865,64 @@ function findEmbeddedAttributes(value, carrierVr, encoding, isActionable) {
|
|
|
15353
16865
|
return void 0;
|
|
15354
16866
|
}
|
|
15355
16867
|
|
|
15356
|
-
// src/deident/
|
|
15357
|
-
|
|
15358
|
-
"
|
|
15359
|
-
|
|
15360
|
-
|
|
15361
|
-
|
|
15362
|
-
|
|
15363
|
-
"
|
|
15364
|
-
"
|
|
15365
|
-
|
|
15366
|
-
|
|
15367
|
-
|
|
15368
|
-
var
|
|
15369
|
-
|
|
16868
|
+
// src/deident/method-codes.ts
|
|
16869
|
+
function row(codeValue, codeMeaning) {
|
|
16870
|
+
return Object.freeze({ codeValue, codingSchemeDesignator: "DCM", codeMeaning });
|
|
16871
|
+
}
|
|
16872
|
+
var BASIC_PROFILE = row("113100", "Basic Application Confidentiality Profile");
|
|
16873
|
+
var CLEAN_PIXEL_DATA = row("113101", "Clean Pixel Data Option");
|
|
16874
|
+
var CLEAN_RECOGNIZABLE_VISUAL_FEATURES = row(
|
|
16875
|
+
"113102",
|
|
16876
|
+
"Clean Recognizable Visual Features Option"
|
|
16877
|
+
);
|
|
16878
|
+
var CLEAN_GRAPHICS = row("113103", "Clean Graphics Option");
|
|
16879
|
+
var CLEAN_STRUCTURED_CONTENT = row("113104", "Clean Structured Content Option");
|
|
16880
|
+
var CLEAN_DESCRIPTORS = row("113105", "Clean Descriptors Option");
|
|
16881
|
+
var RETAIN_TEMPORAL_FULL_DATES = row(
|
|
16882
|
+
"113106",
|
|
16883
|
+
"Retain Longitudinal Temporal Information Full Dates Option"
|
|
16884
|
+
);
|
|
16885
|
+
var RETAIN_TEMPORAL_MODIFIED_DATES = row(
|
|
16886
|
+
"113107",
|
|
16887
|
+
"Retain Longitudinal Temporal Information Modified Dates Option"
|
|
16888
|
+
);
|
|
16889
|
+
var RETAIN_PATIENT_CHARACTERISTICS = row("113108", "Retain Patient Characteristics Option");
|
|
16890
|
+
var RETAIN_DEVICE_IDENTITY = row("113109", "Retain Device Identity Option");
|
|
16891
|
+
var RETAIN_UIDS = row("113110", "Retain UIDs Option");
|
|
16892
|
+
var RETAIN_SAFE_PRIVATE = row("113111", "Retain Safe Private Option");
|
|
16893
|
+
var RETAIN_INSTITUTION_IDENTITY = row("113112", "Retain Institution Identity Option");
|
|
16894
|
+
var DEIDENTIFICATION_METHOD_CODES = Object.freeze({
|
|
16895
|
+
contextGroupUid: "1.2.840.10008.6.1.925",
|
|
16896
|
+
contextGroupVersion: "20170914",
|
|
16897
|
+
rows: Object.freeze([
|
|
16898
|
+
BASIC_PROFILE,
|
|
16899
|
+
CLEAN_PIXEL_DATA,
|
|
16900
|
+
CLEAN_RECOGNIZABLE_VISUAL_FEATURES,
|
|
16901
|
+
CLEAN_GRAPHICS,
|
|
16902
|
+
CLEAN_STRUCTURED_CONTENT,
|
|
16903
|
+
CLEAN_DESCRIPTORS,
|
|
16904
|
+
RETAIN_TEMPORAL_FULL_DATES,
|
|
16905
|
+
RETAIN_TEMPORAL_MODIFIED_DATES,
|
|
16906
|
+
RETAIN_PATIENT_CHARACTERISTICS,
|
|
16907
|
+
RETAIN_DEVICE_IDENTITY,
|
|
16908
|
+
RETAIN_UIDS,
|
|
16909
|
+
RETAIN_SAFE_PRIVATE,
|
|
16910
|
+
RETAIN_INSTITUTION_IDENTITY
|
|
16911
|
+
]),
|
|
16912
|
+
profile: BASIC_PROFILE,
|
|
16913
|
+
options: Object.freeze({
|
|
16914
|
+
CleanGraphics: CLEAN_GRAPHICS,
|
|
16915
|
+
CleanStructuredContent: CLEAN_STRUCTURED_CONTENT,
|
|
16916
|
+
CleanDescriptors: CLEAN_DESCRIPTORS,
|
|
16917
|
+
RetainLongitudinalTemporal: RETAIN_TEMPORAL_FULL_DATES,
|
|
16918
|
+
RetainLongitudinalTemporalModifiedDates: RETAIN_TEMPORAL_MODIFIED_DATES,
|
|
16919
|
+
RetainPatientCharacteristics: RETAIN_PATIENT_CHARACTERISTICS,
|
|
16920
|
+
RetainDeviceIdentity: RETAIN_DEVICE_IDENTITY,
|
|
16921
|
+
RetainUIDs: RETAIN_UIDS,
|
|
16922
|
+
RetainSafePrivate: RETAIN_SAFE_PRIVATE,
|
|
16923
|
+
RetainInstitutionIdentity: RETAIN_INSTITUTION_IDENTITY
|
|
16924
|
+
})
|
|
15370
16925
|
});
|
|
15371
|
-
var DeidentifyError = class extends Error {
|
|
15372
|
-
code;
|
|
15373
|
-
/**
|
|
15374
|
-
* @param message Human-readable, PHI-free description.
|
|
15375
|
-
* @param code One of {@link DEIDENTIFY_ERROR_CODES}.
|
|
15376
|
-
*/
|
|
15377
|
-
constructor(message, code) {
|
|
15378
|
-
super(message);
|
|
15379
|
-
this.name = "DeidentifyError";
|
|
15380
|
-
this.code = code;
|
|
15381
|
-
}
|
|
15382
|
-
};
|
|
15383
16926
|
var DEFAULT_UID_ROOT = "2.25";
|
|
15384
16927
|
var ROOT_RE = /^[0-9]+(\.[0-9]+)*$/;
|
|
15385
16928
|
var MAX_UID_LENGTH = 64;
|
|
@@ -15416,8 +16959,51 @@ function deriveUid(root, sourceUid) {
|
|
|
15416
16959
|
// src/deident/deidentify.ts
|
|
15417
16960
|
var TAG_PATIENT_IDENTITY_REMOVED = "00120062";
|
|
15418
16961
|
var TAG_DEIDENTIFICATION_METHOD = "00120063";
|
|
16962
|
+
var TAG_DEIDENTIFICATION_METHOD_CODE_SEQUENCE = "00120064";
|
|
16963
|
+
var TAG_CODE_VALUE = "00080100";
|
|
16964
|
+
var TAG_CODING_SCHEME_DESIGNATOR = "00080102";
|
|
16965
|
+
var TAG_CODE_MEANING = "00080104";
|
|
15419
16966
|
var TAG_PIXEL_DATA = "7FE00010";
|
|
15420
16967
|
var TAG_BURNED_IN_ANNOTATION = "00280301";
|
|
16968
|
+
var TAG_LONGITUDINAL_TEMPORAL_INFORMATION_MODIFIED = "00280303";
|
|
16969
|
+
var TAG_PRIVATE_DATA_ELEMENT_CHARACTERISTICS_SEQUENCE = "00080300";
|
|
16970
|
+
var TAG_PRIVATE_GROUP_REFERENCE = "00080301";
|
|
16971
|
+
var TAG_PRIVATE_CREATOR_REFERENCE = "00080302";
|
|
16972
|
+
var TAG_BLOCK_IDENTIFYING_INFORMATION_STATUS = "00080303";
|
|
16973
|
+
var TAG_NONIDENTIFYING_PRIVATE_ELEMENTS = "00080304";
|
|
16974
|
+
var TEMPORAL_OPTIONS = Object.freeze([
|
|
16975
|
+
"RetainLongitudinalTemporal",
|
|
16976
|
+
"RetainLongitudinalTemporalModifiedDates"
|
|
16977
|
+
]);
|
|
16978
|
+
var TEMPORAL_STATE = {
|
|
16979
|
+
removed: "REMOVED",
|
|
16980
|
+
unmodified: "UNMODIFIED",
|
|
16981
|
+
modified: "MODIFIED"
|
|
16982
|
+
};
|
|
16983
|
+
function temporalState(active) {
|
|
16984
|
+
if (active.has("RetainLongitudinalTemporalModifiedDates")) return TEMPORAL_STATE.modified;
|
|
16985
|
+
if (active.has("RetainLongitudinalTemporal")) return TEMPORAL_STATE.unmodified;
|
|
16986
|
+
return TEMPORAL_STATE.removed;
|
|
16987
|
+
}
|
|
16988
|
+
var GROUP_0004_PREFIX = "0004";
|
|
16989
|
+
var GROUP_LENGTH_ELEMENT = 0;
|
|
16990
|
+
var FILE_META_GROUP = 2;
|
|
16991
|
+
var MEDIA_STORAGE_DIRECTORY_STORAGE_UID2 = "1.2.840.10008.1.3.10";
|
|
16992
|
+
var MAX_FILE_META_DROP_FINDINGS = 64;
|
|
16993
|
+
var MAX_GROUP_0004_FINDINGS = 64;
|
|
16994
|
+
var MAX_UNREGISTERED_ELEMENT_FINDINGS = 64;
|
|
16995
|
+
var REFUSED_TRANSFER_SYNTAXES = new Set(JPIP_REFERENCED_UIDS);
|
|
16996
|
+
var REFUSED_TRANSFER_SYNTAX_MESSAGE = "deidentify does not de-identify an object under a JPIP Referenced Transfer Syntax (PS3.5 2026c sections A.6, A.7, A.11 and A.12): its Pixel Data Provider URL (0028,7FE0) has no PS3.15 Table E.1-1 action and would be kept by omission. Nothing was de-identified.";
|
|
16997
|
+
function isRefusedTransferSyntax(transferSyntaxUID) {
|
|
16998
|
+
if (transferSyntaxUID === void 0) return false;
|
|
16999
|
+
let end = transferSyntaxUID.length;
|
|
17000
|
+
while (end > 0) {
|
|
17001
|
+
const last = transferSyntaxUID.charCodeAt(end - 1);
|
|
17002
|
+
if (last !== 0 && last !== 32) break;
|
|
17003
|
+
end -= 1;
|
|
17004
|
+
}
|
|
17005
|
+
return REFUSED_TRANSFER_SYNTAXES.has(transferSyntaxUID.slice(0, end));
|
|
17006
|
+
}
|
|
15421
17007
|
var BODY_ENCODING2 = {
|
|
15422
17008
|
"1.2.840.10008.1.2": "implicit",
|
|
15423
17009
|
"1.2.840.10008.1.2.1": "explicitLE",
|
|
@@ -15426,6 +17012,7 @@ var BODY_ENCODING2 = {
|
|
|
15426
17012
|
};
|
|
15427
17013
|
var MAX_UNAUDITABLE_SEQUENCE_FINDINGS = 64;
|
|
15428
17014
|
var MAX_UNDEFINED_VR_FINDINGS = 64;
|
|
17015
|
+
var MAX_PRIVATE_DECLARATION_WARNINGS = 64;
|
|
15429
17016
|
function validateRetain(retain) {
|
|
15430
17017
|
const valid = new Set(DEIDENTIFY_OPTIONS);
|
|
15431
17018
|
const active = /* @__PURE__ */ new Set();
|
|
@@ -15438,16 +17025,13 @@ function validateRetain(retain) {
|
|
|
15438
17025
|
}
|
|
15439
17026
|
active.add(opt);
|
|
15440
17027
|
}
|
|
15441
|
-
|
|
15442
|
-
|
|
15443
|
-
|
|
15444
|
-
|
|
15445
|
-
|
|
15446
|
-
const override = action.optionSet[opt];
|
|
15447
|
-
if (override !== void 0) return override;
|
|
15448
|
-
}
|
|
17028
|
+
if (TEMPORAL_OPTIONS.every((opt) => active.has(opt))) {
|
|
17029
|
+
throw new DeidentifyError(
|
|
17030
|
+
`The PS3.15 E.3.6 Retain Longitudinal Temporal Information Options are mutually exclusive; ${TEMPORAL_OPTIONS.join(" and ")} cannot both be active in one call. Pass at most one.`,
|
|
17031
|
+
"INVALID_OPTIONS"
|
|
17032
|
+
);
|
|
15449
17033
|
}
|
|
15450
|
-
return
|
|
17034
|
+
return active;
|
|
15451
17035
|
}
|
|
15452
17036
|
function freshScalar(orig, value, vm) {
|
|
15453
17037
|
const init = {
|
|
@@ -15505,19 +17089,7 @@ function encodeSequenceValue(items, encoding) {
|
|
|
15505
17089
|
}
|
|
15506
17090
|
function rebuildSequence(orig, items, encoding) {
|
|
15507
17091
|
const value = encodeSequenceValue(items, encoding);
|
|
15508
|
-
|
|
15509
|
-
if (encoding === "implicit") {
|
|
15510
|
-
rawBytes = value;
|
|
15511
|
-
} else {
|
|
15512
|
-
const littleEndian = encoding === "explicitLE";
|
|
15513
|
-
const { group, element } = splitTag(orig.tag);
|
|
15514
|
-
const header = Buffer.alloc(12);
|
|
15515
|
-
le16(header, group, 0, littleEndian);
|
|
15516
|
-
le16(header, element, 2, littleEndian);
|
|
15517
|
-
header.write("SQ", 4, "ascii");
|
|
15518
|
-
le32(header, value.length, 8, littleEndian);
|
|
15519
|
-
rawBytes = Buffer.concat([header, value]);
|
|
15520
|
-
}
|
|
17092
|
+
const rawBytes = sequenceRawBytes(orig.tag, value, encoding);
|
|
15521
17093
|
const init = {
|
|
15522
17094
|
tag: orig.tag,
|
|
15523
17095
|
vr: "SQ",
|
|
@@ -15532,6 +17104,30 @@ function rebuildSequence(orig, items, encoding) {
|
|
|
15532
17104
|
};
|
|
15533
17105
|
return new Element(init);
|
|
15534
17106
|
}
|
|
17107
|
+
function sequenceRawBytes(tag, value, encoding) {
|
|
17108
|
+
if (encoding === "implicit") return value;
|
|
17109
|
+
const littleEndian = encoding === "explicitLE";
|
|
17110
|
+
const { group, element } = splitTag(tag);
|
|
17111
|
+
const header = Buffer.alloc(12);
|
|
17112
|
+
le16(header, group, 0, littleEndian);
|
|
17113
|
+
le16(header, element, 2, littleEndian);
|
|
17114
|
+
header.write("SQ", 4, "ascii");
|
|
17115
|
+
le32(header, value.length, 8, littleEndian);
|
|
17116
|
+
return Buffer.concat([header, value]);
|
|
17117
|
+
}
|
|
17118
|
+
function insertedSequence(tag, items, encoding) {
|
|
17119
|
+
const value = encodeSequenceValue(items, encoding);
|
|
17120
|
+
return new Element({
|
|
17121
|
+
tag,
|
|
17122
|
+
vr: "SQ",
|
|
17123
|
+
vm: items.length,
|
|
17124
|
+
length: value.length,
|
|
17125
|
+
rawBytes: sequenceRawBytes(tag, value, encoding),
|
|
17126
|
+
byteOffset: 0,
|
|
17127
|
+
littleEndian: encoding !== "explicitBE",
|
|
17128
|
+
items
|
|
17129
|
+
});
|
|
17130
|
+
}
|
|
15535
17131
|
function decodeCreator(el) {
|
|
15536
17132
|
return el.rawBytes.toString("latin1").replace(/[\0 ]+$/, "").trim();
|
|
15537
17133
|
}
|
|
@@ -15587,17 +17183,57 @@ function isUnauditableSequence(el) {
|
|
|
15587
17183
|
function emptyUnauditableSequence(el, ctx, contextPath, out) {
|
|
15588
17184
|
emptyUnauditableCarrier(el, ctx, contextPath, out, rebuildSequence(el, [], ctx.encoding));
|
|
15589
17185
|
}
|
|
17186
|
+
function isGroup0004(tag) {
|
|
17187
|
+
return tag.slice(0, 4) === GROUP_0004_PREFIX;
|
|
17188
|
+
}
|
|
17189
|
+
function recordGroup0004Removal(tag, ctx, contextPath) {
|
|
17190
|
+
ctx.group0004.total++;
|
|
17191
|
+
if (ctx.group0004.findings.length >= MAX_GROUP_0004_FINDINGS) return;
|
|
17192
|
+
ctx.group0004.findings.push({
|
|
17193
|
+
tag,
|
|
17194
|
+
applied: "removed",
|
|
17195
|
+
...contextPath.length > 0 ? { contextPath: [...contextPath] } : {}
|
|
17196
|
+
});
|
|
17197
|
+
}
|
|
17198
|
+
function isUnregisteredStandardTag(tag) {
|
|
17199
|
+
const { group, element } = splitTag(tag);
|
|
17200
|
+
if (element === GROUP_LENGTH_ELEMENT) return false;
|
|
17201
|
+
if (group === FILE_META_GROUP || isGroup0004(tag)) return false;
|
|
17202
|
+
return !isRegisteredTag(tag);
|
|
17203
|
+
}
|
|
17204
|
+
function removeUnregisteredElement(el, ctx, contextPath) {
|
|
17205
|
+
ctx.unregistered.total++;
|
|
17206
|
+
if (ctx.unregistered.findings.length >= MAX_UNREGISTERED_ELEMENT_FINDINGS) return;
|
|
17207
|
+
ctx.unregistered.findings.push({
|
|
17208
|
+
byteOffset: el.byteOffset,
|
|
17209
|
+
...contextPath.length > 0 ? { contextPath: [...contextPath] } : {}
|
|
17210
|
+
});
|
|
17211
|
+
}
|
|
15590
17212
|
function emptyUnauditableCarrier(el, ctx, contextPath, out, replacement) {
|
|
15591
17213
|
out.elements.set(el.tag, replacement);
|
|
15592
17214
|
if (ctx.budget.unauditableSequences >= MAX_UNAUDITABLE_SEQUENCE_FINDINGS) return;
|
|
15593
17215
|
ctx.budget.unauditableSequences += 1;
|
|
15594
17216
|
out.unauditableSequences.push({
|
|
15595
17217
|
tag: el.tag,
|
|
17218
|
+
applied: "emptied",
|
|
15596
17219
|
byteLength: el.rawBytes.length,
|
|
15597
17220
|
...contextPath.length > 0 ? { contextPath: [...contextPath] } : {}
|
|
15598
17221
|
});
|
|
15599
17222
|
out.warnings.push(sequenceNotAuditable({ byteOffset: el.byteOffset }, el.tag));
|
|
15600
17223
|
}
|
|
17224
|
+
function removeUnenumerablePrivate(el, ctx, contextPath, out) {
|
|
17225
|
+
out.elements.delete(el.tag);
|
|
17226
|
+
out.removedPrivateTags.push(el.tag);
|
|
17227
|
+
out.unenumerablePrivateRemovals.push({
|
|
17228
|
+
tag: el.tag,
|
|
17229
|
+
applied: "removed",
|
|
17230
|
+
reason: "unenumerable",
|
|
17231
|
+
...contextPath.length > 0 ? { contextPath: [...contextPath] } : {}
|
|
17232
|
+
});
|
|
17233
|
+
if (ctx.budget.unenumerableRemovals >= MAX_UNAUDITABLE_SEQUENCE_FINDINGS) return;
|
|
17234
|
+
ctx.budget.unenumerableRemovals += 1;
|
|
17235
|
+
out.warnings.push(privateCarrierNotAuditable({ byteOffset: el.byteOffset }, el.tag));
|
|
17236
|
+
}
|
|
15601
17237
|
function creatorsInScope(source) {
|
|
15602
17238
|
const byBlock = /* @__PURE__ */ new Map();
|
|
15603
17239
|
for (const el of source) {
|
|
@@ -15611,28 +17247,139 @@ function creatorFor(tag, creators) {
|
|
|
15611
17247
|
const { group, element } = splitTag(tag);
|
|
15612
17248
|
return creators.get(`${String(group)}:${String(element >> 8 & 255)}`);
|
|
15613
17249
|
}
|
|
15614
|
-
var
|
|
17250
|
+
var BLOCK_STATUS = {
|
|
17251
|
+
safe: "SAFE",
|
|
17252
|
+
unsafe: "UNSAFE",
|
|
17253
|
+
mixed: "MIXED"
|
|
17254
|
+
};
|
|
17255
|
+
var NO_PRIVATE_DECLARATION = /* @__PURE__ */ new Map();
|
|
17256
|
+
function declarationKey(group, creator) {
|
|
17257
|
+
return `${String(group)}:${creator}`;
|
|
17258
|
+
}
|
|
17259
|
+
function decodeEnumerated(el) {
|
|
17260
|
+
return el.rawBytes.toString("latin1").replace(/[\0 ]+$/, "").trim();
|
|
17261
|
+
}
|
|
17262
|
+
function readUnsignedShorts(el) {
|
|
17263
|
+
const values = [];
|
|
17264
|
+
for (let offset = 0; offset + 2 <= el.rawBytes.length; offset += 2) {
|
|
17265
|
+
values.push(
|
|
17266
|
+
el.littleEndian ? el.rawBytes.readUInt16LE(offset) : el.rawBytes.readUInt16BE(offset)
|
|
17267
|
+
);
|
|
17268
|
+
}
|
|
17269
|
+
return values;
|
|
17270
|
+
}
|
|
17271
|
+
function reservedBlocks(source) {
|
|
17272
|
+
const reserved = /* @__PURE__ */ new Set();
|
|
17273
|
+
for (const el of source) {
|
|
17274
|
+
if (!isPrivateTag(el.tag) || !isPrivateCreatorElement(el.tag)) continue;
|
|
17275
|
+
reserved.add(declarationKey(splitTag(el.tag).group, decodeCreator(el)));
|
|
17276
|
+
}
|
|
17277
|
+
return reserved;
|
|
17278
|
+
}
|
|
17279
|
+
function intersectBlocks(first, second) {
|
|
17280
|
+
if (first.allSafe) return second;
|
|
17281
|
+
if (second.allSafe) return first;
|
|
17282
|
+
const both = /* @__PURE__ */ new Set();
|
|
17283
|
+
for (const element of first.safeElements) {
|
|
17284
|
+
if (second.safeElements.has(element)) both.add(element);
|
|
17285
|
+
}
|
|
17286
|
+
return { allSafe: false, safeElements: both };
|
|
17287
|
+
}
|
|
17288
|
+
var UNRESOLVED_ITEM = { resolved: false };
|
|
17289
|
+
function readDeclaredItem(item, reserved) {
|
|
17290
|
+
const groupEl = item.get(TAG_PRIVATE_GROUP_REFERENCE);
|
|
17291
|
+
const creatorEl = item.get(TAG_PRIVATE_CREATOR_REFERENCE);
|
|
17292
|
+
const statusEl = item.get(TAG_BLOCK_IDENTIFYING_INFORMATION_STATUS);
|
|
17293
|
+
if (groupEl === void 0 || creatorEl === void 0 || statusEl === void 0) {
|
|
17294
|
+
return UNRESOLVED_ITEM;
|
|
17295
|
+
}
|
|
17296
|
+
const group = readUnsignedShorts(groupEl)[0];
|
|
17297
|
+
if (group === void 0 || (group & 1) === 0) return UNRESOLVED_ITEM;
|
|
17298
|
+
const creator = decodeCreator(creatorEl);
|
|
17299
|
+
if (creator.length === 0) return UNRESOLVED_ITEM;
|
|
17300
|
+
const key = declarationKey(group, creator);
|
|
17301
|
+
if (!reserved.has(key)) return UNRESOLVED_ITEM;
|
|
17302
|
+
const status = decodeEnumerated(statusEl);
|
|
17303
|
+
if (status === BLOCK_STATUS.safe) {
|
|
17304
|
+
return { resolved: true, key, block: { allSafe: true, safeElements: /* @__PURE__ */ new Set() } };
|
|
17305
|
+
}
|
|
17306
|
+
if (status === BLOCK_STATUS.unsafe) {
|
|
17307
|
+
return { resolved: true, key, block: { allSafe: false, safeElements: /* @__PURE__ */ new Set() } };
|
|
17308
|
+
}
|
|
17309
|
+
if (status !== BLOCK_STATUS.mixed) return UNRESOLVED_ITEM;
|
|
17310
|
+
const listEl = item.get(TAG_NONIDENTIFYING_PRIVATE_ELEMENTS);
|
|
17311
|
+
if (listEl === void 0) return UNRESOLVED_ITEM;
|
|
17312
|
+
const listed = /* @__PURE__ */ new Set();
|
|
17313
|
+
for (const value of readUnsignedShorts(listEl)) {
|
|
17314
|
+
if (value <= 255) listed.add(value);
|
|
17315
|
+
}
|
|
17316
|
+
if (listed.size === 0) return UNRESOLVED_ITEM;
|
|
17317
|
+
return { resolved: true, key, block: { allSafe: false, safeElements: listed } };
|
|
17318
|
+
}
|
|
17319
|
+
function resolvePrivateDeclaration(source, encoding, budget, warnings) {
|
|
17320
|
+
const at3 = source.findIndex((el) => el.tag === TAG_PRIVATE_DATA_ELEMENT_CHARACTERISTICS_SEQUENCE);
|
|
17321
|
+
const declarationEl = at3 < 0 ? void 0 : source[at3];
|
|
17322
|
+
if (declarationEl?.items === void 0) return NO_PRIVATE_DECLARATION;
|
|
17323
|
+
const bound = settledBound(source, encoding);
|
|
17324
|
+
if (!isSettled(declarationEl, at3, bound)) return NO_PRIVATE_DECLARATION;
|
|
17325
|
+
const reserved = reservedBlocks(source.filter((el, index) => isSettled(el, index, bound)));
|
|
17326
|
+
const declaration = /* @__PURE__ */ new Map();
|
|
17327
|
+
for (const item of declarationEl.items) {
|
|
17328
|
+
const read = readDeclaredItem(item, reserved);
|
|
17329
|
+
if (!read.resolved) {
|
|
17330
|
+
if (budget.privateDeclarationItems >= MAX_PRIVATE_DECLARATION_WARNINGS) continue;
|
|
17331
|
+
budget.privateDeclarationItems += 1;
|
|
17332
|
+
warnings.push(
|
|
17333
|
+
privateDeclarationNotResolved({ byteOffset: declarationEl.byteOffset, fileMeta: false })
|
|
17334
|
+
);
|
|
17335
|
+
continue;
|
|
17336
|
+
}
|
|
17337
|
+
const existing = declaration.get(read.key);
|
|
17338
|
+
declaration.set(
|
|
17339
|
+
read.key,
|
|
17340
|
+
existing === void 0 ? read.block : intersectBlocks(existing, read.block)
|
|
17341
|
+
);
|
|
17342
|
+
}
|
|
17343
|
+
return declaration;
|
|
17344
|
+
}
|
|
17345
|
+
function declaredSafe(el, ctx, creators) {
|
|
17346
|
+
if (ctx.declaration.size === 0) return false;
|
|
17347
|
+
const { group, element } = splitTag(el.tag);
|
|
17348
|
+
if (isPrivateCreatorElement(el.tag)) {
|
|
17349
|
+
const block2 = ctx.declaration.get(declarationKey(group, decodeCreator(el)));
|
|
17350
|
+
if (block2 === void 0) return false;
|
|
17351
|
+
return block2.allSafe || block2.safeElements.size > 0;
|
|
17352
|
+
}
|
|
17353
|
+
const creator = creatorFor(el.tag, creators);
|
|
17354
|
+
if (creator === void 0) return false;
|
|
17355
|
+
const block = ctx.declaration.get(declarationKey(group, creator));
|
|
17356
|
+
if (block === void 0) return false;
|
|
17357
|
+
return block.allSafe || block.safeElements.has(element & 255);
|
|
17358
|
+
}
|
|
17359
|
+
var UNDEFINED_LENGTH8 = 4294967295;
|
|
15615
17360
|
var EXPLICIT_SQ_HEADER_BYTES = 12;
|
|
15616
17361
|
function itemStreamOverrunsSequence(el, encoding) {
|
|
15617
|
-
if (el.vr !== "SQ" || el.length ===
|
|
17362
|
+
if (el.vr !== "SQ" || el.length === UNDEFINED_LENGTH8) return false;
|
|
15618
17363
|
const headerBytes = encoding === "implicit" ? 0 : EXPLICIT_SQ_HEADER_BYTES;
|
|
15619
17364
|
return el.rawBytes.length - headerBytes > el.length;
|
|
15620
17365
|
}
|
|
15621
17366
|
function settledBound(source, encoding) {
|
|
15622
17367
|
let index = source.length;
|
|
15623
17368
|
let byteOffset;
|
|
15624
|
-
for (const [
|
|
17369
|
+
for (const [at3, el] of source.entries()) {
|
|
15625
17370
|
if (!itemStreamOverrunsSequence(el, encoding) && !isUnauditableSequence(el)) continue;
|
|
15626
|
-
if (index === source.length) index =
|
|
17371
|
+
if (index === source.length) index = at3 + 1;
|
|
15627
17372
|
if (byteOffset === void 0 || el.byteOffset < byteOffset) byteOffset = el.byteOffset;
|
|
15628
17373
|
}
|
|
15629
17374
|
return { index, byteOffset };
|
|
15630
17375
|
}
|
|
15631
|
-
function isSettled(el,
|
|
15632
|
-
return
|
|
17376
|
+
function isSettled(el, at3, bound) {
|
|
17377
|
+
return at3 < bound.index && (bound.byteOffset === void 0 || el.byteOffset <= bound.byteOffset);
|
|
15633
17378
|
}
|
|
15634
17379
|
function keepsPrivate(el, ctx, creators) {
|
|
15635
|
-
if (!ctx.active.has("RetainSafePrivate")
|
|
17380
|
+
if (!ctx.active.has("RetainSafePrivate")) return false;
|
|
17381
|
+
if (declaredSafe(el, ctx, creators)) return true;
|
|
17382
|
+
if (ctx.profile === void 0) return false;
|
|
15636
17383
|
if (isPrivateCreatorElement(el.tag)) {
|
|
15637
17384
|
return ctx.profile.privateDictionary.has(decodeCreator(el));
|
|
15638
17385
|
}
|
|
@@ -15659,7 +17406,10 @@ function keepRetainedPrivate(el, ctx, contextPath, out, reservationsUsable, crea
|
|
|
15659
17406
|
emptyUnauditableCarrier(el, ctx, contextPath, out, freshScalar(el, Buffer.alloc(0), 0));
|
|
15660
17407
|
return;
|
|
15661
17408
|
}
|
|
15662
|
-
keepOrEmpty(el, ctx, contextPath, out);
|
|
17409
|
+
if (!keepOrEmpty(el, ctx, contextPath, out)) return;
|
|
17410
|
+
if (isPrivateCreatorElement(el.tag) || el.rawBytes.length === 0) return;
|
|
17411
|
+
if (declaredSafe(el, ctx, creators)) return;
|
|
17412
|
+
removeUnenumerablePrivate(el, ctx, contextPath, out);
|
|
15663
17413
|
}
|
|
15664
17414
|
function processElements(source, ctx, contextPath, reservationsUsable) {
|
|
15665
17415
|
const out = {
|
|
@@ -15668,20 +17418,29 @@ function processElements(source, ctx, contextPath, reservationsUsable) {
|
|
|
15668
17418
|
removedPrivateTags: [],
|
|
15669
17419
|
embeddedAttributes: [],
|
|
15670
17420
|
unauditableSequences: [],
|
|
17421
|
+
unenumerablePrivateRemovals: [],
|
|
15671
17422
|
undefinedVrElements: [],
|
|
15672
17423
|
warnings: []
|
|
15673
17424
|
};
|
|
15674
17425
|
const bound = settledBound(source, ctx.encoding);
|
|
15675
|
-
const creators = creatorsInScope(source.filter((el,
|
|
15676
|
-
for (const [
|
|
17426
|
+
const creators = creatorsInScope(source.filter((el, at3) => isSettled(el, at3, bound)));
|
|
17427
|
+
for (const [at3, el] of source.entries()) {
|
|
17428
|
+
if (ctx.removeGroup0004 && isGroup0004(el.tag)) {
|
|
17429
|
+
recordGroup0004Removal(el.tag, ctx, contextPath);
|
|
17430
|
+
continue;
|
|
17431
|
+
}
|
|
15677
17432
|
if (isPrivateTag(el.tag)) {
|
|
15678
|
-
if (reservationsUsable && isSettled(el,
|
|
17433
|
+
if (reservationsUsable && isSettled(el, at3, bound) && keepsPrivate(el, ctx, creators))
|
|
15679
17434
|
keepRetainedPrivate(el, ctx, contextPath, out, reservationsUsable, creators);
|
|
15680
17435
|
else out.removedPrivateTags.push(el.tag);
|
|
15681
17436
|
continue;
|
|
15682
17437
|
}
|
|
15683
17438
|
const action = annexE(el.tag);
|
|
15684
17439
|
if (action === void 0) {
|
|
17440
|
+
if (isUnregisteredStandardTag(el.tag)) {
|
|
17441
|
+
removeUnregisteredElement(el, ctx, contextPath);
|
|
17442
|
+
continue;
|
|
17443
|
+
}
|
|
15685
17444
|
if (el.vr === "SQ") {
|
|
15686
17445
|
if (isUnauditableSequence(el)) emptyUnauditableSequence(el, ctx, contextPath, out);
|
|
15687
17446
|
else
|
|
@@ -15744,9 +17503,17 @@ function descendSequence(el, ctx, contextPath, out, reservationsUsable) {
|
|
|
15744
17503
|
out.removedPrivateTags.push(...inner.removedPrivateTags);
|
|
15745
17504
|
out.embeddedAttributes.push(...inner.embeddedAttributes);
|
|
15746
17505
|
out.unauditableSequences.push(...inner.unauditableSequences);
|
|
17506
|
+
out.unenumerablePrivateRemovals.push(...inner.unenumerablePrivateRemovals);
|
|
15747
17507
|
out.undefinedVrElements.push(...inner.undefinedVrElements);
|
|
15748
17508
|
out.warnings.push(...inner.warnings);
|
|
15749
|
-
newItems.push(
|
|
17509
|
+
newItems.push(
|
|
17510
|
+
new Item({
|
|
17511
|
+
index,
|
|
17512
|
+
warnings: [],
|
|
17513
|
+
elements: inner.elements,
|
|
17514
|
+
...item.fileOffset !== void 0 ? { fileOffset: item.fileOffset } : {}
|
|
17515
|
+
})
|
|
17516
|
+
);
|
|
15750
17517
|
});
|
|
15751
17518
|
return rebuildSequence(el, newItems, ctx.encoding);
|
|
15752
17519
|
}
|
|
@@ -15796,12 +17563,26 @@ function auditAttribute(tag, source, action, applied, contextPath) {
|
|
|
15796
17563
|
};
|
|
15797
17564
|
}
|
|
15798
17565
|
function rebuildFileMeta(fileMeta, ctx) {
|
|
15799
|
-
if (fileMeta === void 0) return void 0;
|
|
15800
|
-
|
|
15801
|
-
|
|
17566
|
+
if (fileMeta === void 0) return { fileMeta: void 0, dropped: [], droppedCount: 0 };
|
|
17567
|
+
const extras = fileMeta.extraElements ?? [];
|
|
17568
|
+
const dropped = [];
|
|
17569
|
+
for (const extra of extras) {
|
|
17570
|
+
if (dropped.length >= MAX_FILE_META_DROP_FINDINGS) break;
|
|
17571
|
+
dropped.push({ tag: extra.tag, vr: extra.vr, byteLength: extra.value.length });
|
|
17572
|
+
}
|
|
17573
|
+
const sourceSopInstance = fileMeta.mediaStorageSOPInstanceUID;
|
|
17574
|
+
const sopInstance = sourceSopInstance === void 0 || ctx.active.has("RetainUIDs") ? sourceSopInstance : ctx.remap.map(sourceSopInstance);
|
|
15802
17575
|
return {
|
|
15803
|
-
|
|
15804
|
-
|
|
17576
|
+
fileMeta: {
|
|
17577
|
+
transferSyntaxUID: fileMeta.transferSyntaxUID,
|
|
17578
|
+
...fileMeta.mediaStorageSOPClassUID !== void 0 ? { mediaStorageSOPClassUID: fileMeta.mediaStorageSOPClassUID } : {},
|
|
17579
|
+
...sopInstance !== void 0 ? { mediaStorageSOPInstanceUID: sopInstance } : {},
|
|
17580
|
+
...fileMeta.fileMetaInformationVersion !== void 0 ? { fileMetaInformationVersion: fileMeta.fileMetaInformationVersion } : {},
|
|
17581
|
+
implementationClassUID: COSYTE_IMPLEMENTATION_CLASS_UID,
|
|
17582
|
+
implementationVersionName: COSYTE_IMPLEMENTATION_VERSION_NAME
|
|
17583
|
+
},
|
|
17584
|
+
dropped,
|
|
17585
|
+
droppedCount: extras.length
|
|
15805
17586
|
};
|
|
15806
17587
|
}
|
|
15807
17588
|
var DEFAULT_METHOD_PROFILE = "@cosyte/dicom Basic Application Level Confidentiality Profile";
|
|
@@ -15857,6 +17638,58 @@ function splitValues(value) {
|
|
|
15857
17638
|
}
|
|
15858
17639
|
return out;
|
|
15859
17640
|
}
|
|
17641
|
+
function methodCodesForRun(active) {
|
|
17642
|
+
const options = DEIDENTIFY_OPTIONS.filter((option) => active.has(option));
|
|
17643
|
+
return [
|
|
17644
|
+
DEIDENTIFICATION_METHOD_CODES.profile,
|
|
17645
|
+
...options.map((option) => DEIDENTIFICATION_METHOD_CODES.options[option])
|
|
17646
|
+
];
|
|
17647
|
+
}
|
|
17648
|
+
function methodCodeItem(code, index, littleEndian) {
|
|
17649
|
+
const text = (tag, vr, value) => [
|
|
17650
|
+
tag,
|
|
17651
|
+
insertedScalar(tag, vr, padValue(Buffer.from(value, "latin1"), vr), littleEndian)
|
|
17652
|
+
];
|
|
17653
|
+
return new Item({
|
|
17654
|
+
index,
|
|
17655
|
+
warnings: [],
|
|
17656
|
+
elements: new Map([
|
|
17657
|
+
text(TAG_CODE_VALUE, "SH", code.codeValue),
|
|
17658
|
+
text(TAG_CODING_SCHEME_DESIGNATOR, "SH", code.codingSchemeDesignator),
|
|
17659
|
+
text(TAG_CODE_MEANING, "LO", code.codeMeaning)
|
|
17660
|
+
])
|
|
17661
|
+
});
|
|
17662
|
+
}
|
|
17663
|
+
function carriesCode(item, code) {
|
|
17664
|
+
const designator = item.get(TAG_CODING_SCHEME_DESIGNATOR);
|
|
17665
|
+
const value = item.get(TAG_CODE_VALUE);
|
|
17666
|
+
if (designator === void 0 || value === void 0) return false;
|
|
17667
|
+
return trimTrailingPad(designator.rawBytes).equals(
|
|
17668
|
+
Buffer.from(code.codingSchemeDesignator, "latin1")
|
|
17669
|
+
) && trimTrailingPad(value.rawBytes).equals(Buffer.from(code.codeValue, "latin1"));
|
|
17670
|
+
}
|
|
17671
|
+
function holdsNonPadding(el, encoding) {
|
|
17672
|
+
const headed = isFullSpanElement(el, encoding) && el.length !== UNDEFINED_LENGTH8 && el.length <= el.rawBytes.length;
|
|
17673
|
+
const value = headed ? el.rawBytes.subarray(el.rawBytes.length - el.length) : el.rawBytes;
|
|
17674
|
+
return trimTrailingPad(value).length > 0;
|
|
17675
|
+
}
|
|
17676
|
+
function addDeidentificationMethodCodes(source, processed, active, encoding) {
|
|
17677
|
+
const prior = source?.vr === "SQ" && source.items !== void 0 ? processed?.items : void 0;
|
|
17678
|
+
const kept = prior ?? [];
|
|
17679
|
+
const added = methodCodesForRun(active).filter(
|
|
17680
|
+
(code) => !kept.some((item) => carriesCode(item, code))
|
|
17681
|
+
);
|
|
17682
|
+
const littleEndian = encoding !== "explicitBE";
|
|
17683
|
+
const items = [
|
|
17684
|
+
...kept,
|
|
17685
|
+
...added.map((code, i) => methodCodeItem(code, kept.length + i, littleEndian))
|
|
17686
|
+
];
|
|
17687
|
+
return {
|
|
17688
|
+
element: insertedSequence(TAG_DEIDENTIFICATION_METHOD_CODE_SEQUENCE, items, encoding),
|
|
17689
|
+
retainedPrior: kept.length > 0,
|
|
17690
|
+
replacedPrior: source !== void 0 && prior === void 0 && holdsNonPadding(source, encoding)
|
|
17691
|
+
};
|
|
17692
|
+
}
|
|
15860
17693
|
function hasUncleanedBurnedIn(ds) {
|
|
15861
17694
|
if (!ds.has(TAG_PIXEL_DATA)) return false;
|
|
15862
17695
|
const flag = ds.get(TAG_BURNED_IN_ANNOTATION);
|
|
@@ -15864,17 +17697,36 @@ function hasUncleanedBurnedIn(ds) {
|
|
|
15864
17697
|
return flag.rawBytes.toString("latin1").replace(/[\0 ]+$/, "").trim().toUpperCase() !== "NO";
|
|
15865
17698
|
}
|
|
15866
17699
|
function deidentify(ds, options = {}) {
|
|
17700
|
+
if (isRefusedTransferSyntax(ds.fileMeta?.transferSyntaxUID)) {
|
|
17701
|
+
throw new DeidentifyError(
|
|
17702
|
+
REFUSED_TRANSFER_SYNTAX_MESSAGE,
|
|
17703
|
+
DEIDENTIFY_ERROR_CODES.UNSUPPORTED_TRANSFER_SYNTAX
|
|
17704
|
+
);
|
|
17705
|
+
}
|
|
15867
17706
|
const active = validateRetain(options.retain);
|
|
15868
17707
|
const remap = makeUidRemapper(options.uidRoot, options.uidMap);
|
|
15869
17708
|
const tsUid = ds.fileMeta?.transferSyntaxUID ?? "";
|
|
15870
17709
|
const encoding = BODY_ENCODING2[tsUid] ?? "explicitLE";
|
|
15871
17710
|
const littleEndian = encoding !== "explicitBE";
|
|
17711
|
+
const isDicomdir2 = ds.fileMeta?.mediaStorageSOPClassUID === MEDIA_STORAGE_DIRECTORY_STORAGE_UID2;
|
|
17712
|
+
const budget = {
|
|
17713
|
+
unauditableSequences: 0,
|
|
17714
|
+
unenumerableRemovals: 0,
|
|
17715
|
+
undefinedVrElements: 0,
|
|
17716
|
+
privateDeclarationItems: 0
|
|
17717
|
+
};
|
|
17718
|
+
const declarationWarnings = [];
|
|
17719
|
+
const declaration = active.has("RetainSafePrivate") ? resolvePrivateDeclaration(ds.elements(), encoding, budget, declarationWarnings) : NO_PRIVATE_DECLARATION;
|
|
15872
17720
|
const ctx = {
|
|
15873
17721
|
active,
|
|
15874
17722
|
remap,
|
|
15875
17723
|
profile: options.profile,
|
|
15876
17724
|
encoding,
|
|
15877
|
-
|
|
17725
|
+
removeGroup0004: !isDicomdir2,
|
|
17726
|
+
group0004: { findings: [], total: 0 },
|
|
17727
|
+
unregistered: { findings: [], total: 0 },
|
|
17728
|
+
declaration,
|
|
17729
|
+
budget
|
|
15878
17730
|
};
|
|
15879
17731
|
const processed = processElements(ds.elements(), ctx, [], true);
|
|
15880
17732
|
const {
|
|
@@ -15883,6 +17735,7 @@ function deidentify(ds, options = {}) {
|
|
|
15883
17735
|
removedPrivateTags,
|
|
15884
17736
|
embeddedAttributes,
|
|
15885
17737
|
unauditableSequences,
|
|
17738
|
+
unenumerablePrivateRemovals,
|
|
15886
17739
|
undefinedVrElements
|
|
15887
17740
|
} = processed;
|
|
15888
17741
|
elements.set(
|
|
@@ -15896,7 +17749,24 @@ function deidentify(ds, options = {}) {
|
|
|
15896
17749
|
TAG_DEIDENTIFICATION_METHOD,
|
|
15897
17750
|
insertedScalar(TAG_DEIDENTIFICATION_METHOD, "LO", deidentMethod.value, littleEndian)
|
|
15898
17751
|
);
|
|
15899
|
-
const
|
|
17752
|
+
const priorCodes = ds.get(TAG_DEIDENTIFICATION_METHOD_CODE_SEQUENCE);
|
|
17753
|
+
const methodCodes = addDeidentificationMethodCodes(
|
|
17754
|
+
priorCodes,
|
|
17755
|
+
elements.get(TAG_DEIDENTIFICATION_METHOD_CODE_SEQUENCE),
|
|
17756
|
+
active,
|
|
17757
|
+
encoding
|
|
17758
|
+
);
|
|
17759
|
+
elements.set(TAG_DEIDENTIFICATION_METHOD_CODE_SEQUENCE, methodCodes.element);
|
|
17760
|
+
elements.set(
|
|
17761
|
+
TAG_LONGITUDINAL_TEMPORAL_INFORMATION_MODIFIED,
|
|
17762
|
+
insertedScalar(
|
|
17763
|
+
TAG_LONGITUDINAL_TEMPORAL_INFORMATION_MODIFIED,
|
|
17764
|
+
"CS",
|
|
17765
|
+
Buffer.from(temporalState(active), "latin1"),
|
|
17766
|
+
littleEndian
|
|
17767
|
+
)
|
|
17768
|
+
);
|
|
17769
|
+
const warnings = [...declarationWarnings, ...processed.warnings];
|
|
15900
17770
|
if (deidentMethod.replacedPrior) {
|
|
15901
17771
|
warnings.push(
|
|
15902
17772
|
deidentMethodNotAdded({ byteOffset: priorMethod?.byteOffset ?? 0, fileMeta: false })
|
|
@@ -15917,11 +17787,37 @@ function deidentify(ds, options = {}) {
|
|
|
15917
17787
|
deidentMethodValueOverLength({ byteOffset: priorMethod?.byteOffset ?? 0, fileMeta: false })
|
|
15918
17788
|
);
|
|
15919
17789
|
}
|
|
17790
|
+
if (methodCodes.retainedPrior) {
|
|
17791
|
+
warnings.push(
|
|
17792
|
+
deidentMethodCodesPriorRetained({ byteOffset: priorCodes?.byteOffset ?? 0, fileMeta: false })
|
|
17793
|
+
);
|
|
17794
|
+
}
|
|
17795
|
+
if (methodCodes.replacedPrior) {
|
|
17796
|
+
warnings.push(
|
|
17797
|
+
deidentMethodCodesPriorReplaced({ byteOffset: priorCodes?.byteOffset ?? 0, fileMeta: false })
|
|
17798
|
+
);
|
|
17799
|
+
}
|
|
15920
17800
|
if (hasUncleanedBurnedIn(ds)) {
|
|
15921
17801
|
const offset = ds.get(TAG_PIXEL_DATA)?.byteOffset ?? 0;
|
|
15922
17802
|
warnings.push(burnedInAnnotationNotRemoved({ byteOffset: offset, fileMeta: false }));
|
|
15923
17803
|
}
|
|
15924
|
-
|
|
17804
|
+
if (active.has("RetainLongitudinalTemporalModifiedDates")) {
|
|
17805
|
+
warnings.push(datesNotTransformed({ byteOffset: 0, fileMeta: false }));
|
|
17806
|
+
}
|
|
17807
|
+
const rebuiltFileMeta = rebuildFileMeta(ds.fileMeta, ctx);
|
|
17808
|
+
if (rebuiltFileMeta.droppedCount > 0) {
|
|
17809
|
+
warnings.push(fileMetaReplaced({ byteOffset: 0, fileMeta: true }));
|
|
17810
|
+
}
|
|
17811
|
+
if (ctx.group0004.total > 0) {
|
|
17812
|
+
warnings.push(group0004Removed({ byteOffset: 0, fileMeta: false }));
|
|
17813
|
+
}
|
|
17814
|
+
if (ctx.unregistered.total > 0) {
|
|
17815
|
+
warnings.push(unregisteredElementRemoved({ byteOffset: 0, fileMeta: false }));
|
|
17816
|
+
}
|
|
17817
|
+
if (isDicomdir2) {
|
|
17818
|
+
warnings.push(dicomdirFileSetNotDischarged({ byteOffset: 0, fileMeta: true }));
|
|
17819
|
+
}
|
|
17820
|
+
const newFileMeta = rebuiltFileMeta.fileMeta;
|
|
15925
17821
|
const datasetInit = {
|
|
15926
17822
|
warnings: ds.warnings,
|
|
15927
17823
|
elements,
|
|
@@ -15933,7 +17829,14 @@ function deidentify(ds, options = {}) {
|
|
|
15933
17829
|
removedPrivateTags,
|
|
15934
17830
|
embeddedAttributes,
|
|
15935
17831
|
unauditableSequences,
|
|
17832
|
+
unenumerablePrivateRemovals,
|
|
15936
17833
|
undefinedVrElements,
|
|
17834
|
+
fileMetaElementsDropped: rebuiltFileMeta.dropped,
|
|
17835
|
+
fileMetaElementsDroppedCount: rebuiltFileMeta.droppedCount,
|
|
17836
|
+
group0004Removals: ctx.group0004.findings,
|
|
17837
|
+
group0004RemovalCount: ctx.group0004.total,
|
|
17838
|
+
unregisteredElementRemovals: ctx.unregistered.findings,
|
|
17839
|
+
unregisteredElementRemovalCount: ctx.unregistered.total,
|
|
15937
17840
|
uidMap: remap.cache,
|
|
15938
17841
|
warnings,
|
|
15939
17842
|
retained: [...active]
|
|
@@ -15941,6 +17844,6 @@ function deidentify(ds, options = {}) {
|
|
|
15941
17844
|
return { dataset, report };
|
|
15942
17845
|
}
|
|
15943
17846
|
|
|
15944
|
-
export { CODING_SCHEME_OIDS, DEFAULT_UID_ROOT, DEIDENTIFY_ERROR_CODES, DEIDENTIFY_OPTIONS, Dataset, DeidentifyError, DicomParseError, DicomSerializeError, DicomValueError, dictionary_exports as Dictionary, Element, FATAL_CODES, Item, OFFSET_FRAMES, ProfileDefinitionError, SERIALIZE_ERROR_CODES, Sequence, VALUE_ERROR_CODES, VERSION, WARNING_CODES, codingSchemeOid, decodeElementValue, decodeText, defineProfile, deidentify, isKnownCharsetTerm, makeUidRemapper, parseDate, parseDateTime, parseDicom, parsePersonName, parseSpecificCharacterSet, parseTime, profiles, readCode, resolveDecoderLabel, serializeDicom };
|
|
17847
|
+
export { CODING_SCHEME_OIDS, DEFAULT_UID_ROOT, DEIDENTIFICATION_METHOD_CODES, DEIDENTIFY_ERROR_CODES, DEIDENTIFY_OPTIONS, Dataset, DeidentifyError, DicomParseError, DicomSerializeError, DicomValueError, dictionary_exports as Dictionary, Element, FATAL_CODES, Item, OFFSET_FRAMES, ProfileDefinitionError, SERIALIZE_ERROR_CODES, Sequence, VALUE_ERROR_CODES, VERSION, WARNING_CODES, codingSchemeOid, decodeElementValue, decodeText, defineProfile, deidentify, isKnownCharsetTerm, makeUidRemapper, parseDate, parseDateTime, parseDicom, parsePersonName, parseSpecificCharacterSet, parseTime, profiles, readCode, readPixelDataFragments, resolveDecoderLabel, serializeDicom, toDate, toISO, toObject };
|
|
15945
17848
|
//# sourceMappingURL=index.mjs.map
|
|
15946
17849
|
//# sourceMappingURL=index.mjs.map
|