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