@cosyte/dicom 0.0.8 โ 0.0.11
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 +747 -0
- package/README.md +12 -5
- package/dist/index.cjs +229 -55
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +127 -14
- package/dist/index.d.ts +127 -14
- package/dist/index.mjs +229 -55
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
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.0.11";
|
|
15
15
|
|
|
16
16
|
// src/dictionary/index.ts
|
|
17
17
|
var dictionary_exports = {};
|
|
@@ -11703,15 +11703,24 @@ var BE_VR_STRIDE = Object.freeze({
|
|
|
11703
11703
|
UT: 0,
|
|
11704
11704
|
SQ: 0
|
|
11705
11705
|
});
|
|
11706
|
+
var KNOWN_VRS = Object.freeze(
|
|
11707
|
+
new Set(Object.keys(BE_VR_STRIDE))
|
|
11708
|
+
);
|
|
11709
|
+
function isRecognizedVr(vr) {
|
|
11710
|
+
return KNOWN_VRS.has(vr);
|
|
11711
|
+
}
|
|
11706
11712
|
|
|
11707
11713
|
// src/parser/warnings.ts
|
|
11708
11714
|
var WARNING_CODES = {
|
|
11709
11715
|
// === Phase 2 actively emits (D-08 active list - alphabetical-within-prefix per CONTEXT specifics ยง) ===
|
|
11716
|
+
DICOM_DUPLICATE_FILE_META_ELEMENT: "DICOM_DUPLICATE_FILE_META_ELEMENT",
|
|
11717
|
+
DICOM_DUPLICATE_TAG_IN_DATA_SET: "DICOM_DUPLICATE_TAG_IN_DATA_SET",
|
|
11710
11718
|
DICOM_EMPTY_ITEM_IN_SEQUENCE: "DICOM_EMPTY_ITEM_IN_SEQUENCE",
|
|
11711
11719
|
DICOM_FILE_META_GROUP_LENGTH_MISMATCH: "DICOM_FILE_META_GROUP_LENGTH_MISMATCH",
|
|
11712
11720
|
DICOM_FILE_META_GROUP_LENGTH_MISSING: "DICOM_FILE_META_GROUP_LENGTH_MISSING",
|
|
11713
11721
|
DICOM_GROUP_LENGTH_IN_DATASET: "DICOM_GROUP_LENGTH_IN_DATASET",
|
|
11714
11722
|
DICOM_IMPLICIT_VR_FOR_PRIVATE_TAG_WITHOUT_VR: "DICOM_IMPLICIT_VR_FOR_PRIVATE_TAG_WITHOUT_VR",
|
|
11723
|
+
DICOM_ITEM_CROSSES_SEQUENCE_END: "DICOM_ITEM_CROSSES_SEQUENCE_END",
|
|
11715
11724
|
DICOM_MISSING_PREAMBLE: "DICOM_MISSING_PREAMBLE",
|
|
11716
11725
|
DICOM_NONZERO_RESERVED_BYTES: "DICOM_NONZERO_RESERVED_BYTES",
|
|
11717
11726
|
DICOM_ODD_LENGTH_VALUE_PADDED: "DICOM_ODD_LENGTH_VALUE_PADDED",
|
|
@@ -11737,6 +11746,10 @@ var WARNING_CODES = {
|
|
|
11737
11746
|
// reserved by Phase 7 - not emitted in Phase 2
|
|
11738
11747
|
DICOM_DEIDENT_EMBEDDED_ATTRIBUTE_REMOVED: "DICOM_DEIDENT_EMBEDDED_ATTRIBUTE_REMOVED",
|
|
11739
11748
|
// emitted by deidentify(), never by the parser
|
|
11749
|
+
DICOM_DEIDENT_METHOD_NOT_ADDED: "DICOM_DEIDENT_METHOD_NOT_ADDED",
|
|
11750
|
+
// emitted by deidentify(), never by the parser
|
|
11751
|
+
DICOM_DEIDENT_METHOD_PRIOR_RETAINED: "DICOM_DEIDENT_METHOD_PRIOR_RETAINED",
|
|
11752
|
+
// emitted by deidentify(), never by the parser
|
|
11740
11753
|
DICOM_DEIDENT_SEQUENCE_NOT_AUDITABLE: "DICOM_DEIDENT_SEQUENCE_NOT_AUDITABLE",
|
|
11741
11754
|
// emitted by deidentify(), never by the parser
|
|
11742
11755
|
DICOM_DEIDENT_UNDEFINED_VR_NOT_AUDITABLE: "DICOM_DEIDENT_UNDEFINED_VR_NOT_AUDITABLE",
|
|
@@ -11753,10 +11766,44 @@ var WARNING_MESSAGES = Object.freeze({
|
|
|
11753
11766
|
DICOM_VR_MISMATCH: "Element ({tag}) on-wire VR is {vr2}; dictionary lists {vr}. Trusting on-wire VR.",
|
|
11754
11767
|
DICOM_PRIVATE_TAG_NO_CREATOR: "Private element ({tag}) has no Private Creator registered for its block; treating as VR=UN.",
|
|
11755
11768
|
DICOM_GROUP_LENGTH_IN_DATASET: "Retired Group Length element ({tag}) encountered in dataset; preserved as-is.",
|
|
11756
|
-
|
|
11769
|
+
// The tag is deliberately absent, and this is the only *parser* message where
|
|
11770
|
+
// that is true. See `nonzeroReservedBytes`. Kept terse for the same reason the
|
|
11771
|
+
// de-identify messages are: it is emitted once per element, and element count
|
|
11772
|
+
// is attacker-chosen.
|
|
11773
|
+
DICOM_NONZERO_RESERVED_BYTES: "Non-zero reserved bytes between VR and length (first byte {n}, second byte {n2}); ignoring. Tag withheld; the byte offset identifies the element.",
|
|
11757
11774
|
DICOM_SQ_NOT_DESCENDED: "Element ({tag}) resolved to VR=SQ from the dictionary but its defined-length value is not a valid item stream; kept as opaque bytes and NOT descended, so nothing nested inside it is visible to navigation, and deidentify() cannot audit it. See DICOM_DEIDENT_SEQUENCE_NOT_AUDITABLE.",
|
|
11758
11775
|
DICOM_UN_PARSED_AS_SQ: "Element ({tag}) has VR=UN with undefined length; descended as Implicit VR LE sequence per CP-246.",
|
|
11759
11776
|
DICOM_EMPTY_ITEM_IN_SEQUENCE: "Sequence ({tag}) contains an empty item (length=0); tolerated.",
|
|
11777
|
+
// Neither the tag nor the replaced element's value is here, and the tag's
|
|
11778
|
+
// absence is specific to this code rather than caution. See
|
|
11779
|
+
// `duplicateTagInDataSet`. Short by measurement rather than by intention: one
|
|
11780
|
+
// is raised per collision and the collision count is chosen by the input, so a
|
|
11781
|
+
// 400-character draft was measured at 50 M characters over a 1 MiB file and
|
|
11782
|
+
// cut. The reasoning lives in the factory's JSDoc, not in the string.
|
|
11783
|
+
DICOM_DUPLICATE_TAG_IN_DATA_SET: "A Data Element carrying a tag this Data Set already holds replaced the earlier one at this byte offset; that element's value is not in the parsed object. PS3.5 7.1 and 7.5.1. Tag withheld.",
|
|
11784
|
+
// The tag is deliberately absent for the same reason as the code above, and
|
|
11785
|
+
// the surviving copy is named because the File Meta group resolves a repeat
|
|
11786
|
+
// the OPPOSITE way round to a Data Set: first copy wins here, last read wins
|
|
11787
|
+
// there. Short for the same measured reason - one is raised per repeat and the
|
|
11788
|
+
// repeat count is chosen by the input.
|
|
11789
|
+
// ๐ NO SPEC CITATION HERE, AND ITS ABSENCE IS DELIBERATE. A draft ended this
|
|
11790
|
+
// string "PS3.5 7.1.", which asserts that section's "at most once in a Data
|
|
11791
|
+
// Set" governs the File Meta group - the applicability this slice states it
|
|
11792
|
+
// cannot establish, because PS3.10 governs that group and is not vendored
|
|
11793
|
+
// here. Under `{ strict: true }` this string is also the thrown message, so an
|
|
11794
|
+
// unqualified citation there is the claim, not a footnote. Do not put it back.
|
|
11795
|
+
DICOM_DUPLICATE_FILE_META_ELEMENT: "A File Meta Data Element repeats a (0002,xxxx) tag the group already carries; the copy at this byte offset is not in the parsed File Meta, and the FIRST copy of that tag is the one projected. Tag withheld.",
|
|
11796
|
+
// No value and no length: the prior value is the file's own text. The tag is a
|
|
11797
|
+
// constant of this code rather than composed from input, as in the two
|
|
11798
|
+
// (0002,0000) messages above.
|
|
11799
|
+
DICOM_DEIDENT_METHOD_NOT_ADDED: "The De-identification Method this run recorded could not be added beside the value (0012,0063) already carried without exceeding the largest Value Length that VR can encode, so the earlier value was replaced (PS3.15 E.1.1). The replaced text is not in the output.",
|
|
11800
|
+
// No value and no length, for the same reason as the code above: the retained
|
|
11801
|
+
// text is the file's own. The tag is a constant of this code.
|
|
11802
|
+
DICOM_DEIDENT_METHOD_PRIOR_RETAINED: "A De-identification Method (0012,0063) value the source file already carried was kept beside the one this run recorded, as PS3.15 E.1.1 requires. That attribute is not in Table E.1-1, so no rule in this run inspected, audited or redacted those bytes: if the sender wrote identifying text there it is in the de-identified output, under (0012,0062) = YES. The text is withheld from this message.",
|
|
11803
|
+
// The Item's own declared length is deliberately absent. See
|
|
11804
|
+
// `itemCrossesSequenceEnd`; `{n2}` stays because the emit site's
|
|
11805
|
+
// `endLimit < buffer.length` conjunct bounds it by the buffer.
|
|
11806
|
+
DICOM_ITEM_CROSSES_SEQUENCE_END: "Item ({tag}) declares a length reaching past its enclosing sequence's declared end, so it reads the enclosing Data Set's bytes; {n2} bytes remained inside the sequence. The file's two length fields disagree (PS3.5 7.5.1 and 7.5.2 govern them); the item's is used. The declared length is withheld; the byte offset locates the item.",
|
|
11760
11807
|
DICOM_PIXEL_DATA_LENGTH_MISMATCH: "(7FE0,0010) PixelData declared length {n} does not match computed {n2} bytes.",
|
|
11761
11808
|
DICOM_IMPLICIT_VR_FOR_PRIVATE_TAG_WITHOUT_VR: "Private element ({tag}) under Implicit VR LE has no VR override; falling back to UN.",
|
|
11762
11809
|
DICOM_PRIVATE_CREATOR_UNKNOWN: "Private element ({tag}) 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.",
|
|
@@ -11788,7 +11835,6 @@ var WARNING_MESSAGES = Object.freeze({
|
|
|
11788
11835
|
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.",
|
|
11789
11836
|
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."
|
|
11790
11837
|
});
|
|
11791
|
-
var KNOWN_VRS = new Set(Object.keys(BE_VR_STRIDE));
|
|
11792
11838
|
var TAG_SHAPE = /^[0-9A-F]{8}$/u;
|
|
11793
11839
|
function renderTag(tag) {
|
|
11794
11840
|
return tag !== void 0 && TAG_SHAPE.test(tag) ? tag : WITHHELD;
|
|
@@ -11830,9 +11876,8 @@ function privateTagNoCreator(position, tag) {
|
|
|
11830
11876
|
function groupLengthInDataset(position, tag) {
|
|
11831
11877
|
return build(WARNING_CODES.DICOM_GROUP_LENGTH_IN_DATASET, position, { tag });
|
|
11832
11878
|
}
|
|
11833
|
-
function nonzeroReservedBytes(position,
|
|
11879
|
+
function nonzeroReservedBytes(position, first, second) {
|
|
11834
11880
|
return build(WARNING_CODES.DICOM_NONZERO_RESERVED_BYTES, position, {
|
|
11835
|
-
tag,
|
|
11836
11881
|
n: first,
|
|
11837
11882
|
n2: second
|
|
11838
11883
|
});
|
|
@@ -11843,9 +11888,21 @@ function unParsedAsSQ(position, tag) {
|
|
|
11843
11888
|
function sqNotDescended(position, tag) {
|
|
11844
11889
|
return build(WARNING_CODES.DICOM_SQ_NOT_DESCENDED, position, { tag });
|
|
11845
11890
|
}
|
|
11891
|
+
function itemCrossesSequenceEnd(position, tag, availableLength) {
|
|
11892
|
+
return build(WARNING_CODES.DICOM_ITEM_CROSSES_SEQUENCE_END, position, {
|
|
11893
|
+
tag,
|
|
11894
|
+
n2: availableLength
|
|
11895
|
+
});
|
|
11896
|
+
}
|
|
11846
11897
|
function emptyItemInSequence(position, tag) {
|
|
11847
11898
|
return build(WARNING_CODES.DICOM_EMPTY_ITEM_IN_SEQUENCE, position, { tag });
|
|
11848
11899
|
}
|
|
11900
|
+
function duplicateTagInDataSet(position) {
|
|
11901
|
+
return build(WARNING_CODES.DICOM_DUPLICATE_TAG_IN_DATA_SET, position);
|
|
11902
|
+
}
|
|
11903
|
+
function duplicateFileMetaElement(position) {
|
|
11904
|
+
return build(WARNING_CODES.DICOM_DUPLICATE_FILE_META_ELEMENT, position);
|
|
11905
|
+
}
|
|
11849
11906
|
function implicitVRForPrivateTagWithoutVR(position, tag) {
|
|
11850
11907
|
return build(WARNING_CODES.DICOM_IMPLICIT_VR_FOR_PRIVATE_TAG_WITHOUT_VR, position, { tag });
|
|
11851
11908
|
}
|
|
@@ -11855,6 +11912,12 @@ function privateCreatorUnknown(position, tag) {
|
|
|
11855
11912
|
function burnedInAnnotationNotRemoved(position) {
|
|
11856
11913
|
return build(WARNING_CODES.DICOM_BURNED_IN_ANNOTATION_NOT_REMOVED, position);
|
|
11857
11914
|
}
|
|
11915
|
+
function deidentMethodNotAdded(position) {
|
|
11916
|
+
return build(WARNING_CODES.DICOM_DEIDENT_METHOD_NOT_ADDED, position);
|
|
11917
|
+
}
|
|
11918
|
+
function deidentMethodPriorRetained(position) {
|
|
11919
|
+
return build(WARNING_CODES.DICOM_DEIDENT_METHOD_PRIOR_RETAINED, position);
|
|
11920
|
+
}
|
|
11858
11921
|
function embeddedAttributeRemoved(position, tag, vr, count) {
|
|
11859
11922
|
return build(WARNING_CODES.DICOM_DEIDENT_EMBEDDED_ATTRIBUTE_REMOVED, position, {
|
|
11860
11923
|
tag,
|
|
@@ -12036,12 +12099,12 @@ function readExplicitElementHeader(cursor, _ctx, emit) {
|
|
|
12036
12099
|
const vr = vrSlice.toString("ascii");
|
|
12037
12100
|
let length;
|
|
12038
12101
|
let headerLength;
|
|
12039
|
-
if (LONG_FORM_VRS.has(vr)) {
|
|
12102
|
+
if (LONG_FORM_VRS.has(vr) || !isRecognizedVr(vr)) {
|
|
12040
12103
|
const reserved0 = cursor.buffer[cursor.position];
|
|
12041
12104
|
const reserved1 = cursor.buffer[cursor.position + 1];
|
|
12042
12105
|
cursor.position += 2;
|
|
12043
12106
|
if ((reserved0 ?? 0) !== 0 || (reserved1 ?? 0) !== 0) {
|
|
12044
|
-
emit(nonzeroReservedBytes({ byteOffset: headerStart },
|
|
12107
|
+
emit(nonzeroReservedBytes({ byteOffset: headerStart }, reserved0 ?? 0, reserved1 ?? 0));
|
|
12045
12108
|
}
|
|
12046
12109
|
length = cursor.readUInt32();
|
|
12047
12110
|
headerLength = 12;
|
|
@@ -12149,6 +12212,16 @@ function parseFileMeta(buffer$1, datasetStart, ctx, emit) {
|
|
|
12149
12212
|
fmElements.push(next);
|
|
12150
12213
|
}
|
|
12151
12214
|
}
|
|
12215
|
+
const seenModeledTags = /* @__PURE__ */ new Set();
|
|
12216
|
+
if (declaredFmLength !== void 0) seenModeledTags.add("00020000");
|
|
12217
|
+
for (const e of fmElements) {
|
|
12218
|
+
if (!MODELED_FM_TAGS.has(e.tag)) continue;
|
|
12219
|
+
if (seenModeledTags.has(e.tag)) {
|
|
12220
|
+
emit(duplicateFileMetaElement({ byteOffset: e.byteOffset, fileMeta: true }));
|
|
12221
|
+
continue;
|
|
12222
|
+
}
|
|
12223
|
+
seenModeledTags.add(e.tag);
|
|
12224
|
+
}
|
|
12152
12225
|
const tsElement = fmElements.find((e) => e.tag === "00020010");
|
|
12153
12226
|
if (tsElement === void 0 || tsElement.vr !== "UI") {
|
|
12154
12227
|
throw new DicomParseError(
|
|
@@ -12179,7 +12252,7 @@ function readExplicitLeElement(cursor) {
|
|
|
12179
12252
|
const vr = cursor.slice(2).toString("ascii");
|
|
12180
12253
|
let length;
|
|
12181
12254
|
let headerLength;
|
|
12182
|
-
if (LONG_FORM_VRS.has(vr)) {
|
|
12255
|
+
if (LONG_FORM_VRS.has(vr) || !isRecognizedVr(vr)) {
|
|
12183
12256
|
cursor.slice(2);
|
|
12184
12257
|
length = cursor.readUInt32();
|
|
12185
12258
|
headerLength = 12;
|
|
@@ -12195,7 +12268,7 @@ function readExplicitLeElement(cursor) {
|
|
|
12195
12268
|
if (bytesConsumed !== headerLength + length) {
|
|
12196
12269
|
throw new RangeError("File Meta element accounting mismatch");
|
|
12197
12270
|
}
|
|
12198
|
-
return { tag, vr, value, bytesConsumed };
|
|
12271
|
+
return { tag, vr, value, bytesConsumed, byteOffset: headerStart };
|
|
12199
12272
|
}
|
|
12200
12273
|
function trimUI(buf) {
|
|
12201
12274
|
let end = buf.length;
|
|
@@ -12635,6 +12708,14 @@ var Element = class {
|
|
|
12635
12708
|
}
|
|
12636
12709
|
};
|
|
12637
12710
|
|
|
12711
|
+
// src/parser/data-set-map.ts
|
|
12712
|
+
function defineElement(elements, element, emit) {
|
|
12713
|
+
if (elements.has(element.tag)) {
|
|
12714
|
+
emit(duplicateTagInDataSet({ byteOffset: element.byteOffset }));
|
|
12715
|
+
}
|
|
12716
|
+
elements.set(element.tag, element);
|
|
12717
|
+
}
|
|
12718
|
+
|
|
12638
12719
|
// src/dataset/item.ts
|
|
12639
12720
|
var Item = class extends Dataset {
|
|
12640
12721
|
index;
|
|
@@ -12756,6 +12837,15 @@ function parseSequence(buffer, valueStart, ctx, emit, opts) {
|
|
|
12756
12837
|
items.push(new Item({ warnings: [], elements: inner.elements, index: itemIndex }));
|
|
12757
12838
|
cursor.position = inner.endOffset;
|
|
12758
12839
|
} else {
|
|
12840
|
+
if (opts.explicitLength !== void 0 && endLimit < buffer.length && cursor.position + itemLength > endLimit) {
|
|
12841
|
+
emit(
|
|
12842
|
+
itemCrossesSequenceEnd(
|
|
12843
|
+
{ byteOffset: itemHeaderStart },
|
|
12844
|
+
itemTag,
|
|
12845
|
+
Math.max(0, endLimit - cursor.position)
|
|
12846
|
+
)
|
|
12847
|
+
);
|
|
12848
|
+
}
|
|
12759
12849
|
if (cursor.position + itemLength > buffer.length) {
|
|
12760
12850
|
throw new DicomParseError(
|
|
12761
12851
|
FATAL_CODES.INVALID_FILE_META,
|
|
@@ -12891,8 +12981,8 @@ function parseImplicitLE(buffer, datasetStart, ctx, emit, opts = {}) {
|
|
|
12891
12981
|
cursor.position = seq.endOffset;
|
|
12892
12982
|
const rawBytes = ctx.copyValues ? copyValueBytes(buffer.subarray(valueRawStart, cursor.position)) : buffer.subarray(valueRawStart, cursor.position);
|
|
12893
12983
|
const privateCreator2 = safeModelCreator(resolvePrivateCreator(tag, ctx), ctx);
|
|
12894
|
-
|
|
12895
|
-
|
|
12984
|
+
defineElement(
|
|
12985
|
+
elements,
|
|
12896
12986
|
new Element({
|
|
12897
12987
|
tag,
|
|
12898
12988
|
vr,
|
|
@@ -12903,7 +12993,8 @@ function parseImplicitLE(buffer, datasetStart, ctx, emit, opts = {}) {
|
|
|
12903
12993
|
littleEndian: true,
|
|
12904
12994
|
items: seq.items,
|
|
12905
12995
|
...privateCreator2 !== void 0 ? { privateCreator: privateCreator2 } : {}
|
|
12906
|
-
})
|
|
12996
|
+
}),
|
|
12997
|
+
emit
|
|
12907
12998
|
);
|
|
12908
12999
|
continue;
|
|
12909
13000
|
}
|
|
@@ -12922,8 +13013,8 @@ function parseImplicitLE(buffer, datasetStart, ctx, emit, opts = {}) {
|
|
|
12922
13013
|
cursor.position = cp246.endOffset;
|
|
12923
13014
|
const rawBytes = ctx.copyValues ? copyValueBytes(buffer.subarray(valueRawStart, cursor.position)) : buffer.subarray(valueRawStart, cursor.position);
|
|
12924
13015
|
const privateCreator2 = safeModelCreator(resolvePrivateCreator(tag, ctx), ctx);
|
|
12925
|
-
|
|
12926
|
-
|
|
13016
|
+
defineElement(
|
|
13017
|
+
elements,
|
|
12927
13018
|
new Element({
|
|
12928
13019
|
tag,
|
|
12929
13020
|
vr: "SQ",
|
|
@@ -12936,7 +13027,8 @@ function parseImplicitLE(buffer, datasetStart, ctx, emit, opts = {}) {
|
|
|
12936
13027
|
littleEndian: true,
|
|
12937
13028
|
items: cp246.items,
|
|
12938
13029
|
...privateCreator2 !== void 0 ? { privateCreator: privateCreator2 } : {}
|
|
12939
|
-
})
|
|
13030
|
+
}),
|
|
13031
|
+
emit
|
|
12940
13032
|
);
|
|
12941
13033
|
continue;
|
|
12942
13034
|
}
|
|
@@ -12972,8 +13064,8 @@ function parseImplicitLE(buffer, datasetStart, ctx, emit, opts = {}) {
|
|
|
12972
13064
|
);
|
|
12973
13065
|
if (seq.success) {
|
|
12974
13066
|
const privateCreator2 = safeModelCreator(resolvePrivateCreator(tag, ctx), ctx);
|
|
12975
|
-
|
|
12976
|
-
|
|
13067
|
+
defineElement(
|
|
13068
|
+
elements,
|
|
12977
13069
|
new Element({
|
|
12978
13070
|
tag,
|
|
12979
13071
|
vr,
|
|
@@ -12984,7 +13076,8 @@ function parseImplicitLE(buffer, datasetStart, ctx, emit, opts = {}) {
|
|
|
12984
13076
|
littleEndian: true,
|
|
12985
13077
|
items: seq.items,
|
|
12986
13078
|
...privateCreator2 !== void 0 ? { privateCreator: privateCreator2 } : {}
|
|
12987
|
-
})
|
|
13079
|
+
}),
|
|
13080
|
+
emit
|
|
12988
13081
|
);
|
|
12989
13082
|
continue;
|
|
12990
13083
|
}
|
|
@@ -12997,8 +13090,8 @@ function parseImplicitLE(buffer, datasetStart, ctx, emit, opts = {}) {
|
|
|
12997
13090
|
}
|
|
12998
13091
|
applySpecificCharacterSet(tag, valueSlice, ctx, emit, position);
|
|
12999
13092
|
const privateCreator = safeModelCreator(resolvePrivateCreator(tag, ctx), ctx);
|
|
13000
|
-
|
|
13001
|
-
|
|
13093
|
+
defineElement(
|
|
13094
|
+
elements,
|
|
13002
13095
|
new Element({
|
|
13003
13096
|
tag,
|
|
13004
13097
|
vr,
|
|
@@ -13010,7 +13103,8 @@ function parseImplicitLE(buffer, datasetStart, ctx, emit, opts = {}) {
|
|
|
13010
13103
|
littleEndian: true,
|
|
13011
13104
|
...ctx.currentCharset !== void 0 ? { specificCharacterSet: ctx.currentCharset } : {},
|
|
13012
13105
|
...privateCreator !== void 0 ? { privateCreator } : {}
|
|
13013
|
-
})
|
|
13106
|
+
}),
|
|
13107
|
+
emit
|
|
13014
13108
|
);
|
|
13015
13109
|
}
|
|
13016
13110
|
return { elements, endOffset: cursor.position };
|
|
@@ -13117,8 +13211,8 @@ function _parseExplicit(buffer, datasetStart, ctx, emit, mode, opts = {}) {
|
|
|
13117
13211
|
cursor.position = seqResult.endOffset;
|
|
13118
13212
|
const rawBytes = ctx.copyValues ? copyValueBytes(buffer.subarray(headerStart, cursor.position)) : buffer.subarray(headerStart, cursor.position);
|
|
13119
13213
|
const privateCreator2 = safeModelCreator(resolvePrivateCreator(tag, ctx), ctx);
|
|
13120
|
-
|
|
13121
|
-
|
|
13214
|
+
defineElement(
|
|
13215
|
+
elements,
|
|
13122
13216
|
new Element({
|
|
13123
13217
|
tag,
|
|
13124
13218
|
vr: "SQ",
|
|
@@ -13129,7 +13223,8 @@ function _parseExplicit(buffer, datasetStart, ctx, emit, mode, opts = {}) {
|
|
|
13129
13223
|
littleEndian: mode.littleEndian,
|
|
13130
13224
|
items: seqResult.items,
|
|
13131
13225
|
...privateCreator2 !== void 0 ? { privateCreator: privateCreator2 } : {}
|
|
13132
|
-
})
|
|
13226
|
+
}),
|
|
13227
|
+
emit
|
|
13133
13228
|
);
|
|
13134
13229
|
continue;
|
|
13135
13230
|
}
|
|
@@ -13144,8 +13239,8 @@ function _parseExplicit(buffer, datasetStart, ctx, emit, mode, opts = {}) {
|
|
|
13144
13239
|
const result = parseSequence(buffer, valueStart2, ctx, emit, seqOpts);
|
|
13145
13240
|
cursor.position = result.endOffset;
|
|
13146
13241
|
const rawBytes = ctx.copyValues ? copyValueBytes(buffer.subarray(headerStart, cursor.position)) : buffer.subarray(headerStart, cursor.position);
|
|
13147
|
-
|
|
13148
|
-
|
|
13242
|
+
defineElement(
|
|
13243
|
+
elements,
|
|
13149
13244
|
new Element({
|
|
13150
13245
|
tag,
|
|
13151
13246
|
vr: "OB",
|
|
@@ -13156,7 +13251,8 @@ function _parseExplicit(buffer, datasetStart, ctx, emit, mode, opts = {}) {
|
|
|
13156
13251
|
byteOffset: headerStart,
|
|
13157
13252
|
littleEndian: mode.littleEndian,
|
|
13158
13253
|
items: result.items
|
|
13159
|
-
})
|
|
13254
|
+
}),
|
|
13255
|
+
emit
|
|
13160
13256
|
);
|
|
13161
13257
|
continue;
|
|
13162
13258
|
}
|
|
@@ -13175,8 +13271,8 @@ function _parseExplicit(buffer, datasetStart, ctx, emit, mode, opts = {}) {
|
|
|
13175
13271
|
cursor.position = cp246.endOffset;
|
|
13176
13272
|
const rawBytes = ctx.copyValues ? copyValueBytes(buffer.subarray(headerStart, cursor.position)) : buffer.subarray(headerStart, cursor.position);
|
|
13177
13273
|
const privateCreator3 = safeModelCreator(resolvePrivateCreator(tag, ctx), ctx);
|
|
13178
|
-
|
|
13179
|
-
|
|
13274
|
+
defineElement(
|
|
13275
|
+
elements,
|
|
13180
13276
|
new Element({
|
|
13181
13277
|
tag,
|
|
13182
13278
|
vr: "SQ",
|
|
@@ -13189,15 +13285,16 @@ function _parseExplicit(buffer, datasetStart, ctx, emit, mode, opts = {}) {
|
|
|
13189
13285
|
littleEndian: mode.littleEndian,
|
|
13190
13286
|
items: cp246.items,
|
|
13191
13287
|
...privateCreator3 !== void 0 ? { privateCreator: privateCreator3 } : {}
|
|
13192
|
-
})
|
|
13288
|
+
}),
|
|
13289
|
+
emit
|
|
13193
13290
|
);
|
|
13194
13291
|
continue;
|
|
13195
13292
|
}
|
|
13196
13293
|
const privateCreator2 = safeModelCreator(resolvePrivateCreator(tag, ctx), ctx);
|
|
13197
13294
|
const fallbackEnd = buffer.length;
|
|
13198
13295
|
const fallbackBytes = ctx.copyValues ? copyValueBytes(buffer.subarray(headerStart, fallbackEnd)) : buffer.subarray(headerStart, fallbackEnd);
|
|
13199
|
-
|
|
13200
|
-
|
|
13296
|
+
defineElement(
|
|
13297
|
+
elements,
|
|
13201
13298
|
new Element({
|
|
13202
13299
|
tag,
|
|
13203
13300
|
vr: "UN",
|
|
@@ -13207,7 +13304,8 @@ function _parseExplicit(buffer, datasetStart, ctx, emit, mode, opts = {}) {
|
|
|
13207
13304
|
byteOffset: headerStart,
|
|
13208
13305
|
littleEndian: mode.littleEndian,
|
|
13209
13306
|
...privateCreator2 !== void 0 ? { privateCreator: privateCreator2 } : {}
|
|
13210
|
-
})
|
|
13307
|
+
}),
|
|
13308
|
+
emit
|
|
13211
13309
|
);
|
|
13212
13310
|
cursor.position = fallbackEnd;
|
|
13213
13311
|
continue;
|
|
@@ -13242,8 +13340,8 @@ function _parseExplicit(buffer, datasetStart, ctx, emit, mode, opts = {}) {
|
|
|
13242
13340
|
applySpecificCharacterSet(tag, valueSlice, ctx, emit, position);
|
|
13243
13341
|
const privateCreator = safeModelCreator(resolvePrivateCreator(tag, ctx), ctx);
|
|
13244
13342
|
const finalVr = vr;
|
|
13245
|
-
|
|
13246
|
-
|
|
13343
|
+
defineElement(
|
|
13344
|
+
elements,
|
|
13247
13345
|
new Element({
|
|
13248
13346
|
tag,
|
|
13249
13347
|
vr: finalVr,
|
|
@@ -13255,7 +13353,8 @@ function _parseExplicit(buffer, datasetStart, ctx, emit, mode, opts = {}) {
|
|
|
13255
13353
|
littleEndian: mode.littleEndian,
|
|
13256
13354
|
...ctx.currentCharset !== void 0 ? { specificCharacterSet: ctx.currentCharset } : {},
|
|
13257
13355
|
...privateCreator !== void 0 ? { privateCreator } : {}
|
|
13258
|
-
})
|
|
13356
|
+
}),
|
|
13357
|
+
emit
|
|
13259
13358
|
);
|
|
13260
13359
|
}
|
|
13261
13360
|
return { elements, endOffset: cursor.position };
|
|
@@ -13453,7 +13552,7 @@ function encodeDatasetElement(el, encoding) {
|
|
|
13453
13552
|
}
|
|
13454
13553
|
const littleEndian = encoding === "explicitLE";
|
|
13455
13554
|
const vrBuf = buffer.Buffer.from(el.vr, "ascii");
|
|
13456
|
-
if (LONG_FORM_VRS.has(el.vr)) {
|
|
13555
|
+
if (LONG_FORM_VRS.has(el.vr) || !isRecognizedVr(el.vr)) {
|
|
13457
13556
|
return buffer.Buffer.concat([
|
|
13458
13557
|
uint16(group, littleEndian),
|
|
13459
13558
|
uint16(element, littleEndian),
|
|
@@ -13504,7 +13603,7 @@ function encodeMetaElement(tag, vr, rawValue) {
|
|
|
13504
13603
|
const elementBuf = buffer.Buffer.alloc(2);
|
|
13505
13604
|
elementBuf.writeUInt16LE(element, 0);
|
|
13506
13605
|
const vrBuf = buffer.Buffer.from(vr, "ascii");
|
|
13507
|
-
if (LONG_FORM_VRS.has(vr)) {
|
|
13606
|
+
if (LONG_FORM_VRS.has(vr) || !isRecognizedVr(vr)) {
|
|
13508
13607
|
const lengthBuf2 = buffer.Buffer.alloc(4);
|
|
13509
13608
|
lengthBuf2.writeUInt32LE(value.length, 0);
|
|
13510
13609
|
return buffer.Buffer.concat([
|
|
@@ -14699,7 +14798,6 @@ function uidValueMultiplicity(rawBytes) {
|
|
|
14699
14798
|
}
|
|
14700
14799
|
|
|
14701
14800
|
// src/deident/embedded.ts
|
|
14702
|
-
var KNOWN_VRS2 = new Set(Object.keys(BE_VR_STRIDE));
|
|
14703
14801
|
var UNDEFINED_LENGTH4 = 4294967295;
|
|
14704
14802
|
var FFFE_GROUP = 65534;
|
|
14705
14803
|
var SCANNABLE_CARRIER_VRS = /* @__PURE__ */ new Set([
|
|
@@ -14760,7 +14858,7 @@ function decodeAt(value, off, encoding) {
|
|
|
14760
14858
|
return next2 > value.length ? void 0 : { next: next2, tag };
|
|
14761
14859
|
}
|
|
14762
14860
|
const vr = value.toString("latin1", off + 4, off + 6);
|
|
14763
|
-
if (!
|
|
14861
|
+
if (!KNOWN_VRS.has(vr)) return void 0;
|
|
14764
14862
|
if (LONG_FORM_VRS.has(vr)) {
|
|
14765
14863
|
if (off + 12 > value.length) return void 0;
|
|
14766
14864
|
if (value[off + 6] !== 0 || value[off + 7] !== 0) return void 0;
|
|
@@ -14897,7 +14995,6 @@ var BODY_ENCODING2 = {
|
|
|
14897
14995
|
};
|
|
14898
14996
|
var MAX_UNAUDITABLE_SEQUENCE_FINDINGS = 64;
|
|
14899
14997
|
var MAX_UNDEFINED_VR_FINDINGS = 64;
|
|
14900
|
-
var KNOWN_VRS3 = new Set(Object.keys(BE_VR_STRIDE));
|
|
14901
14998
|
function validateRetain(retain) {
|
|
14902
14999
|
const valid = new Set(DEIDENTIFY_OPTIONS);
|
|
14903
15000
|
const active = /* @__PURE__ */ new Set();
|
|
@@ -15018,7 +15115,7 @@ function actsOnTag(tag, ctx) {
|
|
|
15018
15115
|
return resolveAction(effectiveCode(action, ctx.active)) !== "K";
|
|
15019
15116
|
}
|
|
15020
15117
|
function hasUndefinedVr(el) {
|
|
15021
|
-
return !
|
|
15118
|
+
return !KNOWN_VRS.has(el.vr);
|
|
15022
15119
|
}
|
|
15023
15120
|
function keepOrEmpty(el, ctx, contextPath, out) {
|
|
15024
15121
|
if (hasUndefinedVr(el)) {
|
|
@@ -15082,6 +15179,26 @@ function creatorFor(tag, creators) {
|
|
|
15082
15179
|
const { group, element } = splitTag(tag);
|
|
15083
15180
|
return creators.get(`${String(group)}:${String(element >> 8 & 255)}`);
|
|
15084
15181
|
}
|
|
15182
|
+
var UNDEFINED_LENGTH5 = 4294967295;
|
|
15183
|
+
var EXPLICIT_SQ_HEADER_BYTES = 12;
|
|
15184
|
+
function itemStreamOverrunsSequence(el, encoding) {
|
|
15185
|
+
if (el.vr !== "SQ" || el.length === UNDEFINED_LENGTH5) return false;
|
|
15186
|
+
const headerBytes = encoding === "implicit" ? 0 : EXPLICIT_SQ_HEADER_BYTES;
|
|
15187
|
+
return el.rawBytes.length - headerBytes > el.length;
|
|
15188
|
+
}
|
|
15189
|
+
function settledBound(source, encoding) {
|
|
15190
|
+
let index = source.length;
|
|
15191
|
+
let byteOffset;
|
|
15192
|
+
for (const [at, el] of source.entries()) {
|
|
15193
|
+
if (!itemStreamOverrunsSequence(el, encoding) && !isUnauditableSequence(el)) continue;
|
|
15194
|
+
if (index === source.length) index = at + 1;
|
|
15195
|
+
if (byteOffset === void 0 || el.byteOffset < byteOffset) byteOffset = el.byteOffset;
|
|
15196
|
+
}
|
|
15197
|
+
return { index, byteOffset };
|
|
15198
|
+
}
|
|
15199
|
+
function isSettled(el, at, bound) {
|
|
15200
|
+
return at < bound.index && (bound.byteOffset === void 0 || el.byteOffset <= bound.byteOffset);
|
|
15201
|
+
}
|
|
15085
15202
|
function keepsPrivate(el, ctx, creators) {
|
|
15086
15203
|
if (!ctx.active.has("RetainSafePrivate") || ctx.profile === void 0) return false;
|
|
15087
15204
|
if (isPrivateCreatorElement(el.tag)) {
|
|
@@ -15091,7 +15208,7 @@ function keepsPrivate(el, ctx, creators) {
|
|
|
15091
15208
|
if (creator === void 0) return false;
|
|
15092
15209
|
return resolvePrivateTag(ctx.profile, el.tag, creator) !== void 0;
|
|
15093
15210
|
}
|
|
15094
|
-
function processElements(source, ctx, contextPath) {
|
|
15211
|
+
function processElements(source, ctx, contextPath, reservationsUsable) {
|
|
15095
15212
|
const out = {
|
|
15096
15213
|
elements: /* @__PURE__ */ new Map(),
|
|
15097
15214
|
attributes: [],
|
|
@@ -15101,10 +15218,12 @@ function processElements(source, ctx, contextPath) {
|
|
|
15101
15218
|
undefinedVrElements: [],
|
|
15102
15219
|
warnings: []
|
|
15103
15220
|
};
|
|
15104
|
-
const
|
|
15105
|
-
|
|
15221
|
+
const bound = settledBound(source, ctx.encoding);
|
|
15222
|
+
const creators = creatorsInScope(source.filter((el, at) => isSettled(el, at, bound)));
|
|
15223
|
+
for (const [at, el] of source.entries()) {
|
|
15106
15224
|
if (isPrivateTag(el.tag)) {
|
|
15107
|
-
if (
|
|
15225
|
+
if (reservationsUsable && isSettled(el, at, bound) && keepsPrivate(el, ctx, creators))
|
|
15226
|
+
keepOrEmpty(el, ctx, contextPath, out);
|
|
15108
15227
|
else out.removedPrivateTags.push(el.tag);
|
|
15109
15228
|
continue;
|
|
15110
15229
|
}
|
|
@@ -15112,7 +15231,8 @@ function processElements(source, ctx, contextPath) {
|
|
|
15112
15231
|
if (action === void 0) {
|
|
15113
15232
|
if (el.vr === "SQ") {
|
|
15114
15233
|
if (isUnauditableSequence(el)) emptyUnauditableSequence(el, ctx, contextPath, out);
|
|
15115
|
-
else
|
|
15234
|
+
else
|
|
15235
|
+
out.elements.set(el.tag, descendSequence(el, ctx, contextPath, out, reservationsUsable));
|
|
15116
15236
|
} else {
|
|
15117
15237
|
keepOrEmpty(el, ctx, contextPath, out);
|
|
15118
15238
|
}
|
|
@@ -15120,7 +15240,7 @@ function processElements(source, ctx, contextPath) {
|
|
|
15120
15240
|
}
|
|
15121
15241
|
const resolved = resolveAction(effectiveCode(action, ctx.active));
|
|
15122
15242
|
if (el.vr === "SQ") {
|
|
15123
|
-
applySequenceAction(el, resolved, action, ctx, contextPath, out);
|
|
15243
|
+
applySequenceAction(el, resolved, action, ctx, contextPath, out, reservationsUsable);
|
|
15124
15244
|
continue;
|
|
15125
15245
|
}
|
|
15126
15246
|
let applied;
|
|
@@ -15161,11 +15281,12 @@ function processElements(source, ctx, contextPath) {
|
|
|
15161
15281
|
}
|
|
15162
15282
|
return out;
|
|
15163
15283
|
}
|
|
15164
|
-
function descendSequence(el, ctx, contextPath, out) {
|
|
15284
|
+
function descendSequence(el, ctx, contextPath, out, reservationsUsable) {
|
|
15285
|
+
const childReservationsUsable = reservationsUsable && !itemStreamOverrunsSequence(el, ctx.encoding);
|
|
15165
15286
|
const newItems = [];
|
|
15166
15287
|
(el.items ?? []).forEach((item, index) => {
|
|
15167
15288
|
const childPath = [...contextPath, `${el.tag}[${String(index)}]`];
|
|
15168
|
-
const inner = processElements(item.elements(), ctx, childPath);
|
|
15289
|
+
const inner = processElements(item.elements(), ctx, childPath, childReservationsUsable);
|
|
15169
15290
|
out.attributes.push(...inner.attributes);
|
|
15170
15291
|
out.removedPrivateTags.push(...inner.removedPrivateTags);
|
|
15171
15292
|
out.embeddedAttributes.push(...inner.embeddedAttributes);
|
|
@@ -15176,7 +15297,7 @@ function descendSequence(el, ctx, contextPath, out) {
|
|
|
15176
15297
|
});
|
|
15177
15298
|
return rebuildSequence(el, newItems, ctx.encoding);
|
|
15178
15299
|
}
|
|
15179
|
-
function applySequenceAction(el, resolved, action, ctx, contextPath, out) {
|
|
15300
|
+
function applySequenceAction(el, resolved, action, ctx, contextPath, out, reservationsUsable) {
|
|
15180
15301
|
let applied;
|
|
15181
15302
|
switch (resolved) {
|
|
15182
15303
|
case "X":
|
|
@@ -15192,7 +15313,7 @@ function applySequenceAction(el, resolved, action, ctx, contextPath, out) {
|
|
|
15192
15313
|
emptyUnauditableSequence(el, ctx, contextPath, out);
|
|
15193
15314
|
applied = "emptied";
|
|
15194
15315
|
} else {
|
|
15195
|
-
out.elements.set(el.tag, descendSequence(el, ctx, contextPath, out));
|
|
15316
|
+
out.elements.set(el.tag, descendSequence(el, ctx, contextPath, out, reservationsUsable));
|
|
15196
15317
|
applied = "cleaned";
|
|
15197
15318
|
}
|
|
15198
15319
|
break;
|
|
@@ -15202,7 +15323,7 @@ function applySequenceAction(el, resolved, action, ctx, contextPath, out) {
|
|
|
15202
15323
|
emptyUnauditableSequence(el, ctx, contextPath, out);
|
|
15203
15324
|
applied = "emptied";
|
|
15204
15325
|
} else {
|
|
15205
|
-
out.elements.set(el.tag, descendSequence(el, ctx, contextPath, out));
|
|
15326
|
+
out.elements.set(el.tag, descendSequence(el, ctx, contextPath, out, reservationsUsable));
|
|
15206
15327
|
applied = "kept";
|
|
15207
15328
|
}
|
|
15208
15329
|
break;
|
|
@@ -15234,6 +15355,47 @@ function defaultMethod(active) {
|
|
|
15234
15355
|
const base = "Cosyte @cosyte/dicom: PS3.15 Basic Application Level Confidentiality Profile";
|
|
15235
15356
|
return active.size === 0 ? base : `${base} + ${[...active].join(", ")}`;
|
|
15236
15357
|
}
|
|
15358
|
+
var VALUE_DELIMITER = 92;
|
|
15359
|
+
var MAX_SHORT_FORM_VALUE_BYTES = 65534;
|
|
15360
|
+
function addDeidentificationMethod(existing, method) {
|
|
15361
|
+
const added = trimTrailingPad(buffer.Buffer.from(method, "latin1"));
|
|
15362
|
+
if (existing === void 0 || existing.vr !== "LO") {
|
|
15363
|
+
return { value: added, replacedPrior: false, retainedPrior: false };
|
|
15364
|
+
}
|
|
15365
|
+
const kept = buffer.Buffer.from(trimTrailingPad(existing.rawBytes));
|
|
15366
|
+
if (kept.length === 0) return { value: added, replacedPrior: false, retainedPrior: false };
|
|
15367
|
+
const keptValues = splitValues(kept).map(trimTrailingPad);
|
|
15368
|
+
const missing = added.length === 0 ? [] : splitValues(added).filter((v) => !keptValues.some((k) => k.equals(trimTrailingPad(v))));
|
|
15369
|
+
const parts = [kept];
|
|
15370
|
+
for (const value2 of missing) {
|
|
15371
|
+
parts.push(buffer.Buffer.from([VALUE_DELIMITER]), value2);
|
|
15372
|
+
}
|
|
15373
|
+
const value = trimTrailingPad(buffer.Buffer.concat(parts));
|
|
15374
|
+
if (value.length > MAX_SHORT_FORM_VALUE_BYTES) {
|
|
15375
|
+
return { value: added, replacedPrior: true, retainedPrior: false };
|
|
15376
|
+
}
|
|
15377
|
+
return { value, replacedPrior: false, retainedPrior: true };
|
|
15378
|
+
}
|
|
15379
|
+
function trimTrailingPad(value) {
|
|
15380
|
+
let end = value.length;
|
|
15381
|
+
while (end > 0) {
|
|
15382
|
+
const last = value[end - 1];
|
|
15383
|
+
if (last === 32 || last === 0) end--;
|
|
15384
|
+
else break;
|
|
15385
|
+
}
|
|
15386
|
+
return value.subarray(0, end);
|
|
15387
|
+
}
|
|
15388
|
+
function splitValues(value) {
|
|
15389
|
+
const out = [];
|
|
15390
|
+
let start = 0;
|
|
15391
|
+
for (let i = 0; i <= value.length; i++) {
|
|
15392
|
+
if (i === value.length || value[i] === VALUE_DELIMITER) {
|
|
15393
|
+
out.push(value.subarray(start, i));
|
|
15394
|
+
start = i + 1;
|
|
15395
|
+
}
|
|
15396
|
+
}
|
|
15397
|
+
return out;
|
|
15398
|
+
}
|
|
15237
15399
|
function hasUncleanedBurnedIn(ds) {
|
|
15238
15400
|
if (!ds.has(TAG_PIXEL_DATA)) return false;
|
|
15239
15401
|
const flag = ds.get(TAG_BURNED_IN_ANNOTATION);
|
|
@@ -15253,7 +15415,7 @@ function deidentify(ds, options = {}) {
|
|
|
15253
15415
|
encoding,
|
|
15254
15416
|
budget: { unauditableSequences: 0, undefinedVrElements: 0 }
|
|
15255
15417
|
};
|
|
15256
|
-
const processed = processElements(ds.elements(), ctx, []);
|
|
15418
|
+
const processed = processElements(ds.elements(), ctx, [], true);
|
|
15257
15419
|
const {
|
|
15258
15420
|
elements,
|
|
15259
15421
|
attributes,
|
|
@@ -15267,11 +15429,23 @@ function deidentify(ds, options = {}) {
|
|
|
15267
15429
|
insertedScalar(TAG_PATIENT_IDENTITY_REMOVED, "CS", buffer.Buffer.from("YES", "latin1"), littleEndian)
|
|
15268
15430
|
);
|
|
15269
15431
|
const method = options.deidentificationMethod ?? defaultMethod(active);
|
|
15432
|
+
const priorMethod = elements.get(TAG_DEIDENTIFICATION_METHOD);
|
|
15433
|
+
const deidentMethod = addDeidentificationMethod(priorMethod, method);
|
|
15270
15434
|
elements.set(
|
|
15271
15435
|
TAG_DEIDENTIFICATION_METHOD,
|
|
15272
|
-
insertedScalar(TAG_DEIDENTIFICATION_METHOD, "LO",
|
|
15436
|
+
insertedScalar(TAG_DEIDENTIFICATION_METHOD, "LO", deidentMethod.value, littleEndian)
|
|
15273
15437
|
);
|
|
15274
15438
|
const warnings = [...processed.warnings];
|
|
15439
|
+
if (deidentMethod.replacedPrior) {
|
|
15440
|
+
warnings.push(
|
|
15441
|
+
deidentMethodNotAdded({ byteOffset: priorMethod?.byteOffset ?? 0, fileMeta: false })
|
|
15442
|
+
);
|
|
15443
|
+
}
|
|
15444
|
+
if (deidentMethod.retainedPrior) {
|
|
15445
|
+
warnings.push(
|
|
15446
|
+
deidentMethodPriorRetained({ byteOffset: priorMethod?.byteOffset ?? 0, fileMeta: false })
|
|
15447
|
+
);
|
|
15448
|
+
}
|
|
15275
15449
|
if (hasUncleanedBurnedIn(ds)) {
|
|
15276
15450
|
const offset = ds.get(TAG_PIXEL_DATA)?.byteOffset ?? 0;
|
|
15277
15451
|
warnings.push(burnedInAnnotationNotRemoved({ byteOffset: offset, fileMeta: false }));
|